10 ms·
One of the goals of any code base of significant size should be to reduce the cognitive load (not lines of code per function). Assume the developer working her
by keyle 4y ago
One of the goals of any code base of significant size should be to reduce the cognitive load (not lines of code per function).
Assume the developer working here just had a 45 mins sync, has a meaningless repeat meeting about vapourware in 10 mins and a 2 hours town hall meeting after lunch... and still have to deliver that mess of a requirement you made him promise to deliver before any of these interruptions were even on his calendar!
- Always aim for declarative programming (abstract out the how it does it),
- limit the depth of the function calls (rabbit hole developers...),
- separate business logic from framework internals and
- choose composition over inheritance.
- Also avoid traits and mixins (run from the dark magic)
- don't over document the language or framework, only the eyebrow raising lines, the performance sensitive stuff and the context surrounding the file if it isn't obvious.
- name stuff to be easily grepable
Easy rules to go by, (there are probably more), they can make or break your ability to work, so that you can get interrupted 12 times an hour and still commit work.
I don't find these in books, just decades of sweating and pulling my hair "why does it have to be so hard!?" I have met plenty of senior devs who naturally do the same thing now.
The code size fallacy is a prime example of the wrong way to look at it. Plenty of extremely large code base in C++ are far more manageable than small JavaScript apps.
Mixing boilerplate framework junk with your intellectual property algorithms "what makes your software yours" is a sure way to hinder productivity in the long term.
You write code 3-4 times. You read it 365 times a year.
One last thing I recommend if you deal with a lot of interruptions and maybe multiple products, various code bases... keep a
// @next reintegrate with X
The @next comment 'marker' is a great way to mark exactly which line of which file you were at before you left this project, for a meeting, for lunch, for the day, etc. And it allows you jump back into context by searching for @next and go. Also since it's visual and located, your brain has a much better time remembering the context, since we're good with places and visual landmarks.
It's far more efficient than roughly remembering what I was doing, looking at the last commit, scrolling endlessly through open files. Don't commit @next though :)
- magicalhippo 4y agoNice list. I would add, near the top, "don't be clever unless it makes the code significantly easier to read for others". For example, if your code involves a lot of linear algebra, then operator overloading the sensible operators is probably a good thing. But don't use operator overloading just to save some keystrokes. Over-abstraction is another such case. Try to avoid adding abstraction layers until you need them. I'd also add "make the code as self-documenting as possible". That means being verbose at the right times, such as writing meaningful identifier names. And of course "avoid global variables". I've seen people use singletons with a read/write member, which is as much a global variable as any other.
- pvillano 4y agogrug write clever code once, grug need to be clever every day forever. grug write readable code instead. readable code maybe need clever now, but no need clever in future
- keyle 4y agoYes, "avoid global variables". I forgot to write that one. In fact, I'd say, try to write everything as stateless as possible. That means no shared variables, functional style programming whenever possible (and logical, not for the sake of it). Debugging a code base with global variables vs. passing what it needs is far easier to reason about when reading the code, but also easier to write tests for. Very good point. State is evil, but of course you need some otherwise your software doesn't do anything real.
- smitty1e 4y agoWe love to hate state, but isn't caching data the key to performance at scale?
- WalterBright 4y agoProgramming maxims inevitably get compromised by the real world. We just try to do our best.
- andreareina 4y agoIt's also famously one of the hard problems.
- q845712 4y agohey seriously, i've been grappling with this: what better candidate to be a global variable than a shared cache that otherwise has to be passed through dozens of function calls (which imo adds cognitive load at many places through the stack).
- drakmaniso 4y ago
- deleted 4y ago[deleted]
- sakras 4y ago> Always aim for declarative programming (abstract out the how it does it) No, no, no! Do not do this because then I have to go read all of the abstractions to actually figure out what the hell my computer is actually doing. It seems nice in theory, but I’ve spent way too many hours stepping through over-abstracted declarative code with my debugger, getting frustrated at the opacity of it all.
- Spivak 4y agoIf your abstraction leaks it’s a nightmare, but if not it’s a dream. When was the last time you had to debug a problem in the Django model code itself?
- deltasevennine 4y agoAll abstractions eventually leak the higher you go. It's just about whether you want to ignore it. These leaks are usually performance related.
- lumost 4y agoAs someone who works on performance sensitive code with great regularity. I would note that moore's law has beaten most attempts to be smart on performance for the last ~20+ years. If code is written correctly, with correct algorithms, in a reasonably performant language - no amount of micro-optimization will beat moore's law.
- anonymoushn 4y agoI have found this to be very far from the truth, with most compute-bound or memory-bound tasks getting 10x speedups from minimal work by stuffing more work into each instruction and retiring more instructions per cycle without really changing the algorithm.
- deltasevennine 4y agoSure. How does this connect with what I mentioned? Not being snarky, but I think I'm missing something because this remark seems to be completely random.
- deleted 4y ago[deleted]
- galaxyLogic 4y agoAbstraction basically means creating your own (domain-specific) language and an interpreter for it. It can greatly help code-understanding if you can grok that domain-specific language easily.
- neeleshs 4y ago+1 for this list. Choosing composition over inheritance is generally a good idea, but if the language doesn't support declarative/automatic delegation, building good compositions becomes tedious. Still, inheritance, when used for code reuse, breaks LSP (https://en.wikipedia.org/wiki/Liskov_substitution_principle https://en.wikipedia.org/wiki/Liskov_substitution_principle) and the problems typically manifest, months or years down the line when you try to extend such areas of code
- rags2riches 4y agoI write the @next comment not as a proper comment, but as straight up text, guaranteed to give me a syntax error the next time I compile. No need to remember to search for anything!
- keyle 4y agoI do that as well! Or this Line of code <<<<<<<<<<<<<<< With pointing, which breaks it. @next is a nice way to formalise a break though.
- Twisol 4y ago> Also avoid traits and mixins (run from the dark magic) I've seen the word "trait" used to mean different things in different language communities. Do you mean it like in Rust, in Ruby, in Scala, or in C++? (Since you mention mixins, I'm guessing like in Ruby?)
- jamesfinlayson 4y ago> Also avoid traits and mixins Too true - I remember working on a PHP project where traits weren't allowed and there were maybe two times that traits would have made life easier but they were easily worked around.
- metaltyphoon 4y ago> I don't find these in books Check out A Philosophy of Software Design, 2nd Edition https://a.co/d/dZ8PJpt https://a.co/d/dZ8PJpt
- arinlen 4y ago> I don't find these in books, just decades of sweating and pulling my hair "why does it have to be so hard!?" You've not been reading good books then. Stuff like "separate business logic from framework internals" is one of the main messages of any book on software architecture, including Bob Martin's classic Clean Architecture. Then "choose composition over inheritance" is Object-oriented programming 101. Then the suggestions to not over comment and "name stuff to be easily grepable" are key takes of Bob Martin's Clean Code. They are all good takes, but hardly unknown.
- Test0129 4y ago> Assume the developer working here just had a 45 mins sync, has a meaningless repeat meeting about vapourware in 10 mins and a 2 hours town hall meeting after lunch... and still have to deliver that mess of a requirement you made him promise to deliver before any of these interruptions were even on his calendar! If I have meetings loaded I am telling whoever is planning the sprint I am reducing my load for meetings. We, as software engineers, cannot allow this nonsense to continue. If I am interrupted 12 times a day I am bringing it up and the next sync. If it doesn't get fixed I am leaving. No one pays me to sit in meetings all day. If you want code delivered leave me alone or burn through young guns that don't know what they want yet. While your post has a lot of good meat it is undermined by this single statement. It's far easier to work when you don't need to proactively reduce cognitive load to caveman levels because developers are by-and-large overworked.
- paskozdilar 4y agoI think the point of that statement was that we should assume the worst case, for the sake of making code easier to deal with for everyone. If the code is easy to deal with for the meeting-ridden hypothetical person, it will definitely be easy to deal with for a non-meeting-ridden hypothetical person. I understand and agree with your frustration, but I don't agree that the statement undermines the parent comment at all.
- qikInNdOutReply 4y agoRegarding the @next, i found the best way to get back into a session after being interrupted, was watching yourselve working on the code. https://github.com/microsoft/codetour https://github.com/microsoft/codetour Basically record the last 5 minutes of your work and replay as code tour.
- tryfinally 4y agoThis seems like overkill, and unless it has a Shadowplay-like mode where you're persistently recording and can just dump the last few minutes to the hard drive, I don't think I'd even know (or remember) when to hit record. (So actually, maybe just use Shadowplay instead?) One other alternative is Idea/Rider's Local History feature which is basically a parallel repo of your entire project that automatically saves a snapshot of your changes every time you save a file. Super useful for all kinds of backtracking, and you don't even need to remember to use it until you actually need it.
- shreyshnaccount 4y agoI am a student, and have a very long way to go. but Jeremy Howard's fastai (part 2 of the deep learning course) really helped me understand why code needs to be understandable. this has given me a lot of appreciation for the art of writing understandable code.
- runald 4y ago> Always aim for declarative programming > limit the depth of the function calls These two are at odds with each other. The more declarative your code is, the deeper your function calls will be. At the extreme case, you will have an DSL-like code that has an intractable stack trace.
- tommica 4y agoThe @next is a good idea - gonna snatch that