Learn to Read Code
kylesletten.com
kylesletten.com
If I see some bit of our code doing something a bit odd, I'm nosy, I'll go and look why. Why does one of our classes use an IDisposable? Why is that property using a custom class? Why is that code using async/await when it looks like it should take nano-seconds?
If it's for a good reason, you'll have invariably found a gotcha, or gained a little more knowledge about the domain you code works in.
But surprisingly often you'll find that it's for a bad reason, or an outdated reason, or someone not really understanding how the functionality they're using works.
In the early days of a language/framework especially, when people really don't understand how it really works, what you see is a lot of cargo-cult code. Doing without understanding. .Net, Jquery, Ruby, Javascript, Typescript, Node, I've seen it happen many times (and of course done it myself too! I remember making loads of pointless singletons in one project a decade ago).
People do something because they don't have the full picture. They make up totally wrong rules like "If I add IDisposable the GC must work better as I believe IDisposable has something to do with the GC so it can't hurt".
A great example right now, in the .Net world, is people are littering their code with async/await. They can't understand it's making their code worse, not better. They don't understand that the performance gain is almost always negligible, but the code complexity increase is expensive.
Moving fast and breaking things adds to the technical debt. The word debt implies that you will have to repay it (or at least, someone will have to repay it). So moving fast now means slowing down later. Sometimes this is desirable, sometimes not.
To expand on the analogy of the OP with regards to unfamiliar words in a novel, I personally don't look up every single word that I come across when I can get an idea of what it means from the context, but only after I encounter it a few times.
I believe what happens is that I form a mental map of the business process and a mental map of the code and then when I eventually come to write something, it just pours out.
Psychologically, it took me a long time to accept that only actually coding 2 or 3 hours a day is fine. For years I beat myself up for being 'lazy'.
EDIT: I mean, it's obviously different if you're just adding an extra column to an existing table or something (usually) trivial like that.
Sure, you won't see much of a difference in response times, but resource usage gets dramatically better, and with it the ability to scale.
If you're working with ASP.Net and you're not using Async/Await, you're doing yourself a disservice.
If that's not your scenario, well then, yeah, dealing with Async/Await is probably not worth the headache.
I flatly disagree with you, this is exactly the cargo-cult programming I'm talking about.
You're thinking about it totally wrong. Async/await is useful if you have a million pipes, but need 2,000,000. Thats millions of requests per second. Virtually no ASP.Net programmer has that need. They usually need 10 or 20 pipes per second, but they need really, really fat ones. Async/await does not make fatter pipes, it lets you use a single pipe as multiple pipes. But for decades IIS already, by default, supplies loads of pipes.
To make it clear, practically speaking, for virtually every asp.net programmer in the world, async/await is utterly pointless.
It's ok for external website calls. Or something you really need to multi-thread. Like the once in a blue moon tasks.
I work in ASP.Net, I rewrite bad async await code, get rid of it AND improve the performance by orders of magnitude.
Performance problems are almost always, in my experience, SQL bottle necks, bad EF queries or stupid loops. And I have fixed serious performance problems for various businesses. Once in 12 years have I seen IIS running out of threads and that was in 2006 when CPUs sucked. And that was fixed by, amazingly, fixing a bad SQL query.
Littering several hundred 40ms controller calls with asynchronous EF calls that run in 3ms won't make your site faster. Fixing that shitty report that locks 20 tables and takes 2000ms to run causing multiple deadlocks and gets called 5 times everytime someone opens your dashboard because you suck at JavaScript will. Put all the async awaits you want into that bugger, it's still going to screw your site over.
Async/await is a load of utter nonsense for the vast majority of MS customers. And yet now I see people using it for the most asinine calls that clearly do not need it.
Yeah, sorry, give me an easy to use benchmark for when to decide to use async/await. Knowing when to use Async/await for .NET has been the biggest minefield so far. And yet you see it in ASP.Net and UWP tutorials.
You're obviously going to see some overhead from the state machines generated, but that's negligible compared to the gains you'll see in throughput and code readability(compared to the older ways of doing async code).
The same reasoning extends to UWP, don't block your main thread with IO so it can still process input. Obviously there's other ways to handle async in a desktop app, but async/await just make it so much easier to reason about your async code. It looks exactly like you're writing synchronous code.
In Java, this might be java.util.Collections package, or java.util.Concurrent. or in C++ that might be Boost. In Elixir, I start with Kernel.ex[0]
https://github.com/elixir-lang/elixir/blob/master/lib/elixir...
~ $ cat empty.c
int main(void) {return 42;}
~ $ gcc -static empty.c -O3
~ $ strip a.out
~ $ size
text data bss dec hex filename
677598 5792 10464 693854 a965e a.out
~ $ diet gcc -static empty.c -O3
~ $ strip a.out
~ $ size
text data bss dec hex filename
901 32 76 1009 3f1 a.outStandard libraries are often a very mixed bag of stuff because things are added but rarely taken away. Some it may be very new, and some of it may have been written before the idioms of a language were even finalized, and then frozen by compatibility needs. If you don't already have a strong sense of good style (or what is currently considered good practice for a language) you may find it difficult to identify what is good and what is a relic of history.
I'm sure that's what he meant...at least I hope
It’s harder to read code than to write it.
I continue to use that line to explain coding to non-coder friends. This article's author seems to understand that as well, but it's worth making explicit.
[1] https://www.joelonsoftware.com/2000/04/06/things-you-should-...
Just like the author found out, it's been there years, no-one's used it.
If you write code that's easy to learn, and if you learn to learn code, you'll simply remember more code. The more code you know, the more productive you gonna be. That's because at one end of the spectrum, you know nothing about the code and you simply cant do nor solve anything. And at the other end of the spectrum, you know all the code, in which case you gonna be able to do whatever you want by definition: analyse it, expand it, rewrite it, refactor it, talk about it, fix it, etc.
This also explains why you want to write code with fewer lines of code (or fewer AST nodes): the more lines (or AST nodes), the more you have to learn. The more you have to learn, the less you know, the less you know, the closer you are from the bad end of the spectrum.
Pair program with someone else who knows the system. Write unit tests.
This process can collapse large amounts of code into a hopefully a single page of text that can be well understood. Without it, I find it very difficult to keep all of the relevant code in my head when it's spread across the code base.
A few questions:
* Do you worry about file names?
* Do you use names from the code or your own shorthand?
* How do you handle conditionals?
I use names from the code. I do want to be able to locate the code later.
I try to omit most conditionals. The goal is to show the path of interest, not all possible paths. Some conditionals are interesting though --very likely errors, process cancellations, scary bug-tempting edge cases.
Complex frameworks are good for getting a project started quickly, but become more and more problematic as a project ages and needs to be debugged.
To me reading source of these frameworks helps realizing that whoever developed them are just human beings like the rest of us and write regular code that's really not special.
I also despise the whole concept of 'validators' in .NET MVC. Not only does it prevent you from using distinct validation for particular actions using the same model, it completely hides the fact that validation is used at all (if you trace the controller code). Why not just write a class that validates the model and use it in the controller? Is that 'too much code/too much coupling' for the controller? Ugh.
I know it's an annoying extra step to learn and do, but when doing anything with refactoring controller actions (e.g. changing action names or required parameters), Ctrl+Shift+F is really your friend. I have noticed references not getting picked up by the refactoring quick actions too, but it was sporadic.
If you skip over unknown words, or just acquire their apparent meaning by guessing from context, you don't really know those words and won't be able to use them effectively, or at all.
It's perfectly fine to gloss over code. You don't have time to understand at a maintainer level every nook and cranny of everything you have to work with.
The solution is easy, using a ToList in the DB call to force it to dl everything first, however to me it shows that the Using is working. Now we find that the black box of Using is empty?
Surrounding yourself with the tools and materials the article suggests makes it more likely you'll turn code-reading into a conversation.
I realize this is a tiny nitpick, but it is "once in a while" not "once and a while"; the latter isn't even grammatical.
The article is otherwise very good.
Does the author ironically mean... by attrition?