26 ms·
Cognitive load is what matters
- seemakani 1y ago[dead]
- delichon 1y agoThe AI version of this is the degradation when the context window gets too large. The fix is the same too, summarize and reset.
- ashwinsundar 1y agoAI does not have a cognitive load problem in remotely the same way people do. People can chunk and re-chunk info based on their skill and experience, but even the best AI just knows one thing - token length
- ijk 1y agoGiven the way attention works, it seems to me that AI has an even more concrete instantiation of cognitive load.
- marginalia_nu 1y agoI think it's pretty tiresome that "smart authors" are blamed for writing complex code. Smart authors generally write simpler code. It's much harder to write simple code than complex for reasons that boil down to entropy -- there are simply many more ways to write complex code than simple code, and finding one of the simple expressions of program logic requires both smarts and a modicum of experience. If you try to do it algorithmically, you arguably won't find a simple expression. It's often glossed over how readability in one axis can drive complexities along another axis, especially when composing code into bite-size readable chunks the actual logic easily gets smeared across many (sometimes dozens) of different functions, making it very hard to figure out what it actually does, even though all the functions check all the boxes for readability, having a single responsibility, etc. E.g. is userAuthorized(request) is true but why is it true? Well because usernamePresent(request) is true and passwordCorrect(user) is true, both of which also decompose into multiple functions and conditions. It's often a smaller cognitive load to just have all that logic in one place, even if it's not the local optimum of readability it may be the global one because needing to constantly skip between methods or modules to figure out what is happening is also incredibly taxing.
- incognito124 1y agoYou reminded me of a rule of thumb that says: Keep the complexities in data structures and simplicity in algorithms
- hibikir 1y agoI have seen subscription systems built following that rule of thumb. It collapses pretty well, as the data structure then becomes impossible to engage with unless you are an expert, and the callers are never experts. Things make more sense when the data structure lives in a world where most, if not all illegal atates become unrepresentable. But given that we often end un building APIs in representations with really weak type systems, doing that becomes impossible.
- winwang 1y agoIronically, the attempt to prevent illegal states may create "complex" code (quoted since it may be due to perceived or actual complexity).
- peacebeard 1y agoIt’s really easy to generalize. Some smart people write simple, maintainable code. Some smart people find it fun to over-complicate. Neither is useful as a generalization in my opinion.
- baobabKoodaa 1y agoWhen an article like this uses the term "smart people", I'm always a bit confused if they mean actually smart people, or not-that-smart-people-who-think-highly-of-themselves. Because there's a lot more people in the latter category, and in my view they are the ones building unnecessary complexity into codebases. To clarify, when I say "not-that-smart-people", I don't mean "stupid people". You need to be beyond some basic level of intelligence in order to have the capability to overcomplicate a codebase. For lack of a better metric, consider IQ. If your IQ is below 80, you are not going to work day-to-day overcomplicating a codebase. You need to be slightly above average intelligence (not stupid, but also "not-that-smart") to find yourself in that position.
- Buttons840 1y agoI'm probably one of the "smart developers" with quirks. I try to build abstractions. I'm both bothered and intrigued by the industry returning to, what I call, "pile-of-if-statements architecture". It's really easy to think it's simple, and it's really easy to think you understand, and it's really easy to close your assigned Jira tickets; so I understand why people like it. People get assigned a task, they look around and find a few places they think are related, then add some if-statements to the pile. Then they test; if the tests fail they add a few more if-statements. Eventually they send it to QA; if QA finds a problem, another quick if-statement will solve the problem. It's released to production, and it works for a high enough percentage of cases that the failure cases don't come to your attention. There's approximately 0% chance the code is actually correct. You just add if-statements until you asymptotically approach correctness. If you accidentally leak the personal data of millions of people, you wont be held responsible, and the cognitive load is always low. But the thing is... I'm not sure there's a better alternative. You can create a fancy abstraction and use a fancy architecture, but I'm not sure this actually increases the odds of the code being correct. Especially in corporate environments--you cannot build a beautiful abstraction in most corporate environments because the owners of the business logic do not treat the business logic with enough care. "A single order ships to a single address, keep it simple, build it, oh actually, a salesman promised a big customer, so now we need to make it so a single order can ship to multiple addresses"--you've heard something like this before, haven't you? You can't build careful bug-free abstractions in corporate environments. So, is pile-of-if-statements the best we can do for business software?
- vasco 1y ago> So, is pile-of-if-statements the best we can do for business software? I'm not sure if that's anywhere in the rating of quality of business software. Things that matter: 1. How fast can I or someone else change it next time to fulfill the next requirements? 2. How often does it fail? 3. How much money does the code save or generate by existing. Good architecture can affect 1 and 2 in some circumstances but not every time and most likely not forever at the rate people are starting to produce LLM garbage code. At some point we'll just compile English directly into bytecode and so architecture will matter even less. And obviously #3 matters by far the most. It's obviously a shame for whoever appreciates the actual art / craft of building software, but that isn't really a thing that matters in business software anyway, at least for the people paying our salaries (or to the users of the software).
- james-bcn 1y agoSome of this reminds me of the recommendations on one of the great programming books, Code Complete: https://en.wikipedia.org/wiki/Code_Complete https://en.wikipedia.org/wiki/Code_Complete
- chrisweekly 1y agoBrilliant essay. Bookmarked for future reference.
- dsego 1y agoI would also recommend A Philosophy of Software Design if you haven't read it, a very short and brilliant read with a similar approach. There is also a discussion between the author of Clean Code and APOSD: https://github.com/johnousterhout/aposd-vs-clean-code https://github.com/johnousterhout/aposd-vs-clean-code
- bob1029 1y agoAt some point, you just need to go with the flow. Worrying about the metacognitive consequences of your work and trying to actively manage this with technological policy will turn into a death spiral. You should always try to take advantage of the momentum in the things around you. Our profession has a reputation for going out of its way to do things like push for a rewrite of a company's codebase after having seen the legacy for 20 minutes. This isn't even a chesterson's fence conversation. This is crude, impulsive behavior that makes any kind of productive business infeasible. Also, many developers are suffering from severe cognitive load that is incurred by technology and tooling tribalism. Every day on HN I see complaints about things like 5 RPS scrapers crippling my web app, error handling, et. al., and all I can think about is how smooth my experience is from my particular ivory tower. We've solved (i.e., completely and permanently) 95% of the problems HN complains about decades ago and you can find a nearly perfect vertical of these solutions with 2-3 vendors right now. Your ten man startup not using Microsoft or Oracle or IBM isn't going to make a single fucking difference to these companies. The only thing you win is a whole universe of new problems that you have to solve from scratch again.
- noen 1y agoThis article reminds me of my early days at Microsoft. I spent 8 years in the Developer Division (DevDiv). Microsoft had three personas for software engineers that were eventually retired for a much more complex persona framework called people in context (the irony in relation to this article isn’t lost on me). But those original personas still stick with me and have been incredibly valuable in my career to understand and work effectively with other engineers. Mort - the pragmatic engineer who cares most about the business outcome. If a “pile of if statements” gets the job done quickly and meets the requirements - Mort became a pejorative term at Microsoft unfortunately. VB developers were often Morts, Access developers were often Morts. Elvis - the rockstar engineer who cares most about doing something new and exciting. Being the first to use the latest framework or technology. Getting visibility and accolades for innovation. The code might be a little unstable - but move fast and break things right? Elvis also cares a lot about the perceived brilliance of their code - 4 layers of abstraction? That must take a genius to understand and Elvis understands it because they wrote it, now everyone will know they are a genius. For many engineers at Microsoft (especially early in career) the assumption was (and still is largely) that Elvis gets promoted because Elvis gets visibility and is always innovating. Einstein - the engineer who cares about the algorithm. Einstein wants to write the most performant, the most elegant, the most technically correct code possible. Einstein cares more if they are writing “pythonic” code than if the output actually solves the business problem. Einstein will refactor 200 lines of code to add a single new conditional to keep the codebase consistent. Einsteins love love love functional languages. None of these personas represent a real engineer - every engineer is a mix, and a human with complex motivations and perspectives - but I can usually pin one of these 3 as the primary within a few days of PRs and a single design review.
- DonHopkins 1y agoIs Microsoft so Balkanized that they have a Developer Division, Developer Multiplication, Developer Addition, and Developer Subtraction (where you get transferred to before they fire you)?
- Waterluvian 1y agoThe larger a corporation gets, the more npm packages you have to first install before accomplishing any meaningful work.
- Buttons840 1y agoIt's been said: "Document the why, not the what." I have a hard time separating the why and the what so I document both. The biggest offender of "documenting the what" is: x = 4 // assign 4 to x Yeah, don't do that. Don't mix a lot of comments into the code. It makes it ugly to read, and the context switching between code and comments is hard. Instead do something like: // I'm going to do // a thing. The code // does the thing. // We need to do the // thing, because the // business needs a // widget and stuff. setup(); t = setupThing(); t.useThing(42); t.theWidget(need=true); t.alsoOtherStuff(); etc(); etc(); Keep the code and comments separate, but stating the what is better than no comments at all, and it does help reduce cognitive load.
- marginalia_nu 1y agoI generally don't mind documenting both when it's merited. Sometimes you need to clarify the why, occasionally you need to clarify the what. I think comments in general are underrated. You don't need to annotate every line like a freshman programming assignment, but on the other hand most supposed self-documenting code just isn't.
- mastermage 1y agosometimes you do some wack magic in just one line of code, sometimes thats necessary for performance or because what you are trying todo is inherently wack magic. Example the fast inverse square from quake. Insane magic and if you just document does inverse square approximately people would freak out. So sometimes when wack magic is used explain the wack magic (as concise as reasonable)
- marginalia_nu 1y agoYup. I've got a function the gist of which is if (!cond()) return val; do { // logic } while (cond()); return val; This looks like it could be simplified as while (cond()) // logic } return val; But if you do you lose out on 20% of performance due to branch mispredictions, and this is a very hot function. It looks like a mistake, like the two are equivalent, but they are actually not. So it gets a comment that explains what's happening.
- makeitdouble 1y agoLowering the cognitive load by assigning temporary variables requires more thought and skill than credited here. In particular these variables need to be extremely well named, otherwise people reading the code will still need to remember what exactly is abstracted if the wording doesn't exactly fit their vision. E.g. > isSecure = condition4 && !condition5 More often than not the real proper name would be "shouldBeSecureBecauseWeAlsoCheckedCondition3Before" To a point, avoiding the abstraction and putting a comment instead can have better readability. The author's "smart" code could as well be ``` if (val > someConstant // is valid && (condition2 || condition3) // is allowed && (condition4 && !condition5) // is secure ) { ... } ```
- cowlby 1y agoOne quirk of AI agents is I've moved to `isValid = val > someConstant` over comments because Cursor (I guess Claude by extension) frequently removes and re-writes comments. Or `isValid = checkForValidity(val, someConstant)` if the condition check grows significantly.
- claytongulick 1y agoI try to structure functions and validations like this in a early-return list at the top of a function. if(val <= someconstant) return; //not valid if(!(condition2 || condition3)) return; //not allowed ... The author mentions this technique as well. I find it particularly useful in controller API functions because it makes the code a lot more auditable (any time I see the same set of conditions repeating a lot, I consider whether they are a good candidate for middleware). I try to explain this to newer developers and they just don't get it, or give me eyerolls. Maybe sending them this article will help.
- SoftTalker 1y agoThey can all be right. I agree assigning variables doesn't help much more than good comments. But worth doing if they are needed more than once in the same scope. But do we need "is valid", "is allowed", and "is secure" more than once in differnt scopes? They should probably functions then. Do we always need all three considered together? Then they should be a single function. Are there ever places where condition2 or condition 3 are not allowed? More complexity. Even simple examples like this get complicated in the real world.
- lxe 1y agoIntroducing intermediate variables is what I call "indirection". You're adding another step to someone reading the code. Let's take a recipe: Ingredients: large bowl 2 eggs 200 grams sugar 500 grams flour 1/2 tsp soda Steps: Crack the eggs into a bowl. Add sugar and whisk. Sift the flower. Add the soda. When following the instruction, you have to always refer back to the ingredients list and search for the quantity, which massively burdens you with "cognitive load". However, if you inline things: Crack 2 eggs into a large bowl. Add 200g sugar and whisk. Sift 500g of flower. Add 1/2 tsp soda. Much easier to follow!
- bathtub365 1y agoWhen making a recipe you usually need to buy some or all of the ingredients. You also want to collect them all together beforehand since it makes things go a lot more smoothly. If they didn’t list them separately it would be easier to miss one.
- mdaniel 1y agoThis probably isn't entirely what you meant, but people who do this code smell drive me starkraving mad shipToAddress(getShippingAddress(getStreet()),calculateShipping(getShippingAddress(getStreet()))) because as soon as one needs to update the mechanism for getting the shipping address, congratulations, you're updating it everywhere -- or not, nothing matters in this timeline
- aDyslecticCrow 1y agoyour example makes me question how much you bake. The instructions are simple to remember, the ingredient quantities are not. Once i have read the recipe, i have a clear idea what i need to do. But i may need to look up the quantities. Looking for those in a block of text is a waste of time and error prone. Having a recipe formatted like the 2nd example is only useful for a someone inexperienced with baking. Its also difficult to buy or bring out the ingredients if they're hidden in text. Or know if i can bake something based on what i have or not. If you've baked an really old recipe from a book, you may find instructions like "Mix the ingredients, put in a pan, bake until brown on high heat", with a list of quantities and not even a picture to know what it is you're baking. An experienced baker will know the right order and tools, and how their oven behaves, so it's not written out at all. If i look for recipes online, seeing the instructions written like you have makes me reluctant to trust the author, and also makes me annoyed when trying to follow or plan out the process.
- 1dom 1y agoThis article makes me feel weird. I think I'm not smart enough for it. I can't really take anything new away from it, mainly just a message of "we're smart people, and trust us when we say smart things are bad. All the smart sounding stuff you learned about how to program from smart sounding people like us? Lol, that's all wrong now." Okay, I get the cognitive load is bad, so what's the solution? "Just do simple dumb stuff, duh." Oh, right... Useful. The problem is never just the code, or the architecture, or the business, or the cognitive load. It's the mismatch of those things against the people expected to work with them. Walk into a team full of not-simple engineers, and tell them all what they've been doing is wrong, and they need to just write simple code, some of them will fail, some will walk out, and you'll be no closer to a solution. I wish I knew of the tech world before 20 years ago, where technical roles were long and stable enough for teams to build their own understanding of a suitable level of complexity. Without that, churn means we all have to aim for the lowest common denominator.
- bheadmaster 1y ago> Okay, I get the cognitive load is bad, so what's the solution? Modularity. Each component in your system should be a (relatively) simple composition of other (smaller) components, in such a way that each component can be understood as a black box, and is interchangable with any other implementation or the same thing.
- 1dom 1y agoFrom the article: > All too often, we end up creating lots of shallow modules, following some vague "a module should be responsible for one, and only one, thing" principle. This is what I'm talking about: this writing is too smart for me, because I can't take any simple answers from it like "modularity" without feeling another part of the article contradicts it with other smart sounding ways of saying don't listen to smart stuff.
- jsd1982 1y agoI think cognitive load has a lot more to do with the paradigm that the code is written in than any particular type of author's contribution to the code. For instance, the object-oriented paradigm by design increases cognitive load by encouraging breaking up otherwise straightforward logic into multiple interfaces, classes, and methods.
- MiscCompFacts 1y agoThis essay was shared 8 months ago and had significant discussion. https://news.ycombinator.com/item?id=42489645 https://news.ycombinator.com/item?id=42489645 (721 comments)
- PeterWhittaker 1y agoThe most important user of my temporary variables, à la "isValid" or "isSecure" is older/later me. I could be adding a new feature six months later, or debugging a customer reported issue a week later. Especially in the latter case, where the pressure is greater and available time more constrained, I love that earlier/younger me was thoughtful enough to take the extra time to make things clear. That this might help others is lagniappe.
- zahlman 1y ago> A lagniappe (/ˈlænjæp/ LAN-yap, /lænˈjæp/ lan-YAP) is "a small gift given to a customer by a merchant at the time of a purchase" (such as a 13th doughnut on purchase of a dozen), or more broadly, "something given or obtained gratuitously or by way of good measure."[2] It can be used more generally as meaning any extra or unexpected benefit.[3] > The word entered English from the Louisiana French adapting a Quechua word brought in to New Orleans by the Spanish Creoles. ... I see.
- PeterWhittaker 1y agoQuite a lovely word. Learned it from Steinem writing a foreword for a Doonesbury collection in which she excoriated Buckley for his use of the term to describe the fourth panel, the main punchline often having come in the third, in his foreword for a previous collection.
- edtechdev 1y agoCognitive load isn't a valid or useful concept: https://edtechdev.wordpress.com/2009/11/16/cognitive-load-theory-failure/ https://edtechdev.wordpress.com/2009/11/16/cognitive-load-th... https://www.tandfonline.com/doi/full/10.1080/00131857.2024.2441389 https://www.tandfonline.com/doi/full/10.1080/00131857.2024.2... There are separate contexts involved here: the coder, the compiler, the runtime, a person trying to understand the code (context of this article), etc. What's better for one context may not be better for another, and programming languages favor certain contexts over others. In this case, since programming languages primarily favor making things easier for the compiler and have barely improved their design and usability in 50 years, both coders and readers should employ third party tools to assist them. AI can help the reader understand the code and the coder generate clearer documentation and labels, on top of using linters, test driven development, literate documentation practices, etc.
- deleted 1y ago[deleted]
- aDyslecticCrow 1y agoThe linked articles seem to primarily criticize three things about connotative load theory; - Difficult to measure and therefore a hard or impossible to empirically study. (a bad scientific theory) - Its application to education and learning theory which where a lot of other techniques are more proven. - The idea that it's a primary mechanism of human learning, which has had a-lot of research showing otherwise. Though those points seem valid, this article does not concern itself deeply with this concept. The word "mental strain" or "limited short term memory" could have been inserted in place of "cognitive load", and the points raised would be valid. In effect the article argues we should minimize the amount of things that need to be taken into consideration at any given point when reading (or writing) code. This claim is quite reasonable irrespective of the scientific bases of CTL which it takes its wording from. So i don't think your criticism is entirely relevant to this article, but raising it does help inform others about issues with the used wording if they happen to want to learn more.
- reikonomusha 1y ago
- noiv 1y agoI spend a few decades in the industry and in even more teams. I think, the quality of code strongly correlates with the team's ability to articulate its members cognitive load and skills. In some projects it is just not opportune to point out a need to skill up, so everybody just accepts whatever in PRs and quality never gets any better. On the other end of the spectrum you hear sentences starting with: "It would help me to understand this more easily, if ...". Guess, what happens over time in these teams?
- reactordev 1y agoBoy if I had a dollar for every “we’ve been doing it wrong” posts. The issue with this stance is, it’s not a zero sum game. There’s no arriving to a point where there isn’t a cognitive load on the task you’re doing. There will always be some sort of load. Pushing things off so that you reduce your load is how social security databases end up on S3. Confusion comes from complexity. Not a high cognitive load. You can have a high load and still know how it all works. I would better word this as Cognitive load increases stress as you have more things to wrestle about in your head. Doesn’t add or remove confusion (unless that’s the kind of person you are), it just adds or removes complexity. An example of a highly complex thing with little to no cognitive load due to conditioning, driving an automobile. A not-complex thing that imparts a huge cognitive load, golf.
- rowanG077 1y agoIt's always interesting that many people who push the cognitive load argument also push for simpler languages. To me once I have learned a language well the features it has don't add to the cognitive load. they become basically second nature. It even has a great benefit, many things that are explicit in simple languages because there is no language support fall away in more complex languages. So more complex languages reduce cognitive load, at least for me.
- aDyslecticCrow 1y agoComplex languages can give the programmer powerful tools to abstract things badly. But those powerful tools can also help make the code clearer if used right. (I'm a real sucker for a map().filter().map().sort().unwrap(), and feel the same logic becomes so unruly to understand if converted to a large loop) I think the sentiment that we should use simpler languages comes abuse of powerful features. Once we've meta-programmed the entire program logic with a 12 layer deep type tree or inheritance chain... we may realize we abused the tool in a way a simple language would have stopped. But at the same time...checking a errno() after a function call just because the language lack result type or exception handling, is clearly too simple. A minor increase in language complexity would have made the code much clearer.
- weiliddat 1y agoExactly, cognitive load is dynamic not static, and you can actually hold many more things in working memory than the oft-repeated 3-7 items (that's more if you're trying memorize and recall unrelated, novel items). Once you commit a particular concept to long-term memory and it's not "leaky" (you have to think through the internal behavior/implementation details), then now you have more tools and ways to describe a collective bunch of lower-level concepts. That's the same feeling programmers used to more powerful languages have to write less powerful languages — instead of using 1 concept to describe what you want, now you have to use multiple things. It's only easier if you've not grokked the concept.
- tester756 1y ago>So more complex languages reduce cognitive load, at least for me. Even C++ and all it's crazy features of last 5-10 years?
- nibblenum 1y agoStill processing this article, but so far enjoying that it opens with some humour, and also shows off logistics ideas that are not locked into one domain if you zoom out. Thank you :)
- supportengineer 1y agoLarge software projects built by humans will always be doomed to fail, because humans like to build the new, and nobody likes to maintain the old.
- mdaniel 1y agoI'm pretty sure this entire thread is filled with "nobody likes to maintain the pile of ifs", since I doubt very seriously it's the age that jams people up, it's finding the correct place to make a surgical change that only produces the net-new behavior without blowing up the world. I guess the rest of that is that often the older a codebase is, the more revenue stream in impacts if something goes wrong
- deleted 1y ago[deleted]
- tenacious_tuna 1y agoI've very much enjoyed maintaining or optimizing or hardening existing systems--I can just never convince my leadership to let me do that. My current org has a terrible case of not-invented-here syndrome, and it's so easy to pitch new projects that solve something that there's already an existing tool for, or building a new feature. We would love to spend time just working within our existing systems and fixing crap abstractions we made under the deadline-gun, but we're not "allowed" to. > [...] humans like to build the new, and nobody likes to maintain the old I think this is certainly true at organizational scale, but most of the people I've met are change-resistant overall.
- bauble 1y agoHumans are the worst programmers, except for all other programmers.
- oh_my_goodness 1y agoI would love to have four chunks in my head. I feel like I have to start writing when I get to #3.
- perlgeek 1y agoI think the origin of the "four chunks in short-term memory" comes from giving people tasks to calculate some numbers, and seeing after how many digits they became noticeably slower. A fact that you need to remember about code might use up more or less short-term memory in a human brain compared to a digit or a number, so don't be ashamed if your number is 3 instead of 4. I also think that my working memory was better when I was 20ish, now at 41 I already feel less fits in and I forget it faster.
- weiliddat 1y agoWhile I support the goal of article, reducing extraneous cognitive load, I think some of the comments, and the article are missing a key point about cognitive load — it depends on the existing mental model the reader/author/developer has about the whole thing. There is no universal truth to reducing cognitive load like reducing abstractions / not relying on frameworks. Reducing cognitive load doesn't happen in a vacuum where simple language constructs trump abstraction/smart language constructs. Writing code, documents, comments, choosing the right design all depend upon who you think is going to interact with those artifacts, and being able to understand what their likely state of mind is when they interact with those artifacts i.e. theory of mind. What is high cognitive load is very different, for e.g. a mixed junior-senior-principal high-churn engineering team versus a homogenous team who have worked in the same codebase and team for 10+ years. I'd argue the examples from the article are not high cognitive load abstractions, but the wrong abstractions that resulted in high cognitive load because they didn't make things simpler to reason about. There's a reason why all modern standard libraries ship with standard list/array/set/hashmap/string/date constructs, so we don't have manually reimplement them. They also give a team who is using the language (a framework in its own way) common vocabulary to talk about nouns and verbs related to those constructs. In essense, it is reducing the cognitive load once the initial learning phase of the language is done. Reading through the examples in the article, what is likely wrong is that the decision to abstract/layer/framework is not chosen because of observation/emergent behavior, but rather because "it sounds cool" aka cargo cult programming or resume-driven programming. If you notice a group of people fumble over the same things over and over again, and then try to introduce a new concept (abstraction/framework/function), and notice that it doesn't improve or makes it harder to understand after the initial learning period, then stop doing it! I know, sunk cost fallacy makes it difficult after you've spent 3 months convincing your PM/EM/CTO that a new framework might help, but then you have bigger problems than high cognitive load / wrong abstractions ;)
- zakirullin 1y agoThere's a chapter about mental models: https://github.com/zakirullin/cognitive-load?tab=readme-ov-file#cognitive-load-in-familiar-projects https://github.com/zakirullin/cognitive-load?tab=readme-ov-f...
- marcelr 1y agowhile i think this is generally good advice, i also think reality isn't easy to define i like what others would call complexity, i always have, and have from very very early on been mindful of that, i think to a fault since i no longer trust my intuition is it good to try to turn wizards into brick layers? is there no other option?
- piskov 1y agoThis is your annual reminder to watch “Simple made easy” by Rich Hickey https://youtu.be/SxdOUGdseq4 https://youtu.be/SxdOUGdseq4
- layer8 1y ago> Then QA engineers come into play: "Hey, I got 403 status, is that expired token or not enough access?" To be fair, the HTTP status line allows for arbitrary informational text, so something like “HTTP/1.1 401 JWT token expired” would be perfectly allowable.
- deleted 1y ago[deleted]
- madman2890 1y ago“Smart developer’s quirks” tend to peak in 3-8 years of experience and fade off thereafter. A hipster will never fade off and instead continue hipster coding alongside their identity in perpetuity.
- riedel 1y agoSpeaking only of intrinsic and extraneous cognitive load oversimplifies things. This works for tasks of pilots (see e.g. NASATLX scores). However, if new information that needs to be learned is in the game there is also germane cognitive load [0]. It is a nice theory, however, practically there is unfortunately no easy way to separate them and look at them totally independently. [0] https://mcdreeamiemusings.com/blog/2019/10/15/the-good-the-bad-and-the-can-be-ugly-the-three-parts-of-cognitive-load https://mcdreeamiemusings.com/blog/2019/10/15/the-good-the-b...
- semiinfinitely 1y agoThe ability to create code that imposes low cognitive load on others not only is a rare and difficult skill to cultivate- it takes active effort and persistence to do even for someone who already has the ability and motivation. I think fundamentally the developer is computing a mental compression of the core ideas - distilling them to their essence - and then making sure that the code exposes only the minimum essential complexity of those ideas. not easy and rare to see in practice
- bombela 1y agoAnd if you do it really well, people think it must have been such an easy problem to solve all along. Since everything always appears so obvious in insight. While the castle of cards of unfathomable complexity is praised for visibly hard work and celebrated with promotions.
- an0malous 1y ago“When you do things right, people won’t be sure you’ve done anything at all”
- goalieca 1y agoThis is bad for promotions. You have to make grand efforts with impacts of saving things that clearly need saving.
- maccard 1y agoThere’s more than one way to get promoted. Being the common factor among projects that succeed is a really really good one, and IME it’s far more common to find people promoted after one successful project than it is to a “noisy Nancy” be promoted.
- peterangular 1y agoAnd, furthermore - being a "noisy Nancy" is often a bad move for your career, socially. As I age, I realize it's more important to get along in most corporate/professional settings than it is to be the person fixing things. All work represents a social entity (person/persons) and when you're the one calling out issues, pushing for proactive measures, and pushing against bad practices/complexity you're typically taking issue with _someone's_ work along the way. This is often seen as a "squeaky wheel" or "noisy Nancy" - or hell, outright antisocial. Most of the time it is not in your best interest to be this person. The people who keep their nose down + mouth shut, those who prioritize marketing their work, and the sycophants are the ones who have longevity and upward trajectory - this is corporate America work culture.
- david_draco 1y agoUnit and Integration testing is great for decreasing cognitive load too. When you are staring at an error stack trace of a complex code base, and go through mentally what could have played out to cause this, it's great to have confidence in components due to testing. Hypothesis/QuickCheck is allows dropping entire classes of worries.
- supernuova 1y agoYes, exactly! If you can trust that each unit is working in all the ways covered in the tests, you can focus on the unit you are developing and not have to keep the other unit in your mind while working on it. And if there is an untested edge case you think might be the cause, you can test that edge case independently from the unit where the issue is occurring, and confirm if it produces the expected result. Good, trusted unit tests are the difference between encapsulation reducing or increasing/complicating cognitive load. (And similar but between components for integration tests). That being said, there will be rare times that the issue is due to something that is only an edge case due to an implementation detail several units deep, and so sometimes you do still need the full picture, but at least it lets you save doing that until you're stumped, which IMO is well worth it if the code is overall well-designed and tested.
- 00yogi 1y agoA similar design principle is called “APIs should be deep, not wide”: https://unterwaditzer.net/2024/api-wrappers.html https://unterwaditzer.net/2024/api-wrappers.html
- zakirullin 1y agoThanks! I might link it to the article.
- xmprt 1y agoThis is one of the reasons I fear AI will harm the software engineering industry. AI doesn't have any of these limitation so it can write extremely complex and unreadable code that works... until it doesn't. And then no one can fix it. It's also why I urge junior engineers to not rely on AI so much because even though it makes writing code so much faster, it prevents them from learning the quirks of the codebase and eventually they'll lose the ability to write code on their own.
- fsckboy 1y ago>AI can write extremely complex and unreadable code that works... until it doesn't. And then AI can fix it I'm not defending or encouraging AI, just saying that argument doesn't work
- xmprt 1y agoI'm talking about cases where even AI can't fix it. I've heard of a lot of stories where people vibe code their applications to 80% and then get stuck in a loop where AI is unable to solve their problems. It's been well documented that LLMs collapse after a certain complexity level.
- fsckboy 1y agoyou were also talking about the future (as AIs get better and better). as of now AIs cannot write code too complex for better programmers to understand. your point holds for armies of low skill programmers, but you're just raising a fear and haven't come close to proving the case you're trying to make. We already know as counterweight that being first to the market with very substandard code generally wins over taking your time to get it right, so why should it be different with AI?
- AstroBen 1y ago> We already know as counterweight that being first to the market with very substandard code generally wins ..we do? Who created short stories as used in Tiktok/IG? The first touch screen phone? First social media app? Was Google the first? I mean I almost see the opposite of what you're saying..
- deleted 1y ago[deleted]
- arnonejoe 1y ago"Domain-driven design has some great points, although it is often misinterpreted”. Agreed. The worst shops I’ve ever worked in are ones where the DDD/evans/fowler orthodoxy has run amok.
- lilerjee 1y agoCognitive Load is not what matters, Solving problems is what matters. "Cognitive Load" is a buzzword which is abstract. Cognitive Load is just one factor of projects, and not the main one. Focus on solving problems, not Cognitive Load, or other abstract concepts. Use the simple, direct, and effective method to solve problems. Cognitive Load is relative, it is a high Cognitive Load for one person, but low cognitive load for another person for the same thing.
- adolph 1y ago"Cognitive Load" may be a buzzword, and not well defined, and that doesn't mean it isn't a useful concept for evaluating different approaches toward solving problems that may extend the useful life of that solution instead of reinventing yet another wheel. Getting to a better understanding of "cognitive load" does seem useful. Some things are "easier" to understand than others. Could things that are less efficient to understand be formulated in a way that is more efficient? I have a notion that "cognitive load" is related to the human's ability to gain and maintain attention to mentally ingesting a solution (along with the problem the solution putatively solves). Interesting reads for this include McGilchrist's Master and His Emissary, and Carolyn Dicey Jennings' "I attend, therefore I am," [0], who was interviewed on the Rutt podcast [1]. 0. https://aeon.co/essays/what-is-the-self-if-not-that-which-pays-attention https://aeon.co/essays/what-is-the-self-if-not-that-which-pa... 1. https://jimruttshow.blubrry.net/the-jim-rutt-show-transcripts/transcript-of-ep-276-carolyn-dicey-jennings-on-attention-and-mental-control/ https://jimruttshow.blubrry.net/the-jim-rutt-show-transcript...
- tartoran 1y ago> Cognitive Load is not what matters, Solving problems is what matters. > Use the simple, direct, and effective method to solve problems. You seem to contradict yourself, while you mention cognitive load is not what matters you prescribe a way to lower cognitive load. I've seen projects explode in complexity and then die and that was mainly to unmanageable cognitive load required to make changes.
- lilerjee 1y agoSolving problems is the purpose and focus. How to solve problems? The simple, direct, and effective method is good one method sometimes, not all time. For example, use very complicated method to obfuscate code in order to increase the difficulty of cracking, and there are many environments to use complicated code or methods. So one is the purpose, one is the method. Do not think "Lower Cognitive Load" is the purpose. "Lower Cognitive load" is just the by-product sometimes, not the purpose.
- vdupras 1y agoI don't know, I'm seduced by the elitist approach: code with a high cognitive load keeps mediocre developers away. Case in point: Forth. It generally has a heavy cognitive load. However, Forth also enables a radical kind of simplicity. You need to be able to handle the load to access it. The mind can train to a high cognitive load. It's a nice "muscle" to train. Should we care about cognitive load? Absolutely. It's a finite budget. But I also think that there are legitimate reasons to accept a high cognitive load for a piece of code. One might ask "what if you need to onboard mediocre developers into your project?". Hum, yeah, sure. In that case, this article is correct. But being forced to onboard mediocre developers highlights an organizational problem.
- winwang 1y agoThis is an interesting take. I have a somewhat orthogonal viewpoint -- rather than "heavy cognitive load", I think that going somewhat off-mainstream is good for attracting, on average, better devs. For example, it's likely that the average Haskell dev spends more time honing their craft than the average Java dev. The article kind of touches on this (e.g. FP "vs" the more popular OOP) with familiarity vs simplicity though.
- noportro 1y ago> code with a high cognitive load keeps mediocre developers away. That's true and it's a positive thing but the downstream consequences are often painful. We had a c/c++ project with complex memory management and heavy multithreadding, written that way because the superstar developer could handle the cognitive load and found the assignment intellectually challenging. That was great until they left for the next job. We were left fighting a codebase with a big cognitive load, so we were desperately dependent on hiring more superstars just for routine maintenance. We eventually concluded that this wasn't a sustainable model and rewrote the system in plain old python. Much happier now.
- vdupras 1y agoThis is what I mean by "organizational problem". I understand that sometimes -- in fact most of the times -- you need to onboard mediocre programmers. But on the other hand, it's really great when you don't have to.
- haffi112 1y agoThe section on nested ifs reminded be of being a Nevernester: https://www.youtube.com/watch?v=CFRhGnuXG-4 https://www.youtube.com/watch?v=CFRhGnuXG-4 (it's a short [~8 min], fun watch)
- AlexCoventry 1y agoHe should cite John Ousterhout, IMO. He's clearly influenced by Ousterhout's (excellent) work.
- zakirullin 1y agoAnd I did it a few times :) He knows about the article, we talked about it.
- roadbuster 1y agoLucky to have an opportunity to chat with him! Did he have any specific feedback on your essay?
- zakirullin 1y agoThere's some: https://groups.google.com/g/software-design-book/c/c_CNaDTJtbI/m/ERTjhQG8AQAJ https://groups.google.com/g/software-design-book/c/c_CNaDTJt...
- AlexCoventry 1y agoHeh, apologies. Should have Ctrl+F'd.
- dennisy 1y agoWhilst I agree with lots of ideas in this piece, I fell out of love with it when clicking into the discussion on what should be done instead of using a layered architecture. The author makes valid points but they are vacuous and do not provide concrete alternatives. Many engineering articles disappoint me in this way, I get hyped by all the “don’t dos”, but the “do dos” never come.
- zakirullin 1y agoSoftware engineering is a relatively immature field. Nobody knows how to cook it in a proper way. What we know for sure is how to fail (point of the article). There was an analogy about building bridges and writing software. Building a bridge is boring, it's a very mature engineering field, and it's clearly known how to do it the best way possible. Software development is far from it. Unknown unknowns, ever changing requirements, different mental models in people's brains...
- trentnix 1y agoCognitive load and the benefits of simplification aren't just for systems and code. Reducing cognitive load is critically important in delivering good requirements. It enables engineers to focus on the technical and organization aspects of the solution, not interpreting the problem. The fact is, despite all the process and pipelines and rituals we've invented to guide how software is made, the best thing leadership can do is to communicate incremental, unambiguous requirements and provide time and space for your engineers to solve the problem. If you don't do that, none of the other meetings and systems and processes and tools will matter.
- guerrilla 1y ago> isValid = val > someConstant > isAllowed = condition2 || condition3 > isSecure = condition4 && !condition5 > // , we don't need to remember the conditions, there are descriptive variables > if isValid && isAllowed && isSecure { > ... >} I literally relaxed in my body when I read this. It was like a deep sigh of cool relief in my soul.
- e40 1y agoThis is why I make lists. Of everything. Checklists for technical processes (work and personal). Checklists for travel. Little "how to" docs on pretty much everything I do that I'm sure I won't remember past a week. It completely removes the stress of doing things repeatedly. I recently had to do something I hadn't done in 2 years. Yep, the checklist/doc on it was 95% correct, but it was no problem fixing the 5%.
- mettamage 1y agoIn like Apple Notes or what do you store the checklists in?
- germandiago 1y agoDepending on the task the most effective way I found sometimes is a hand-written paper stuck on a wall. Why so? It is always in front of you, it reminds you what you need to do and does not get out of sight, which helps keep the focus. When you bury it or set it somewhere else it is very easy to bury it.
- e4325f 1y agoI use Apple Reminders
- ajuc 1y agoTxt files are hard to beat
- danielpoer1098 1y ago[dead]
- computerdork 1y agoI like the digital note-taking tools, Evernote and Onenote - actually, used to use Evernote, but it started slowing down after my notebooks became too large, so switched to Onenote. And eventhough Onenote is MS product and Evernote was the original that OneNote copied off of, OneNote is a better engineered piece of software (I have tons of notes and a few of them very large documents), and Onenote rarely has problems.
- ChrisMarshallNY 1y agoThere's some good stuff in the posting. Certainly giving me some pause for thought, in my own work.
- holysoles 1y agoGreat read. At my last job, everything was quite monolithic when I joined, and I led the crusade to move to more segmented, module-driven development. There was definitely a period where I eventually swung too far in that direction and only realized it after a dependency issue led to an escalation. Hopefully someone can learn from this before they spin a complex web that becomes a huge effort to untangle.
- fatih-erikli-cg 1y ago[dead]
- deleted 1y ago[deleted]
- deleted 1y ago[deleted]
- jakobov 1y agoYes this is the central theme in https://codeisforhumans.com/ https://codeisforhumans.com/
- andix 1y agoI had the exact same experience with layered architectures like described in this article. Avoid them as much as possible, naive and simple code is often better. It might look messy on the surface, and the layered code might look much cleaner. Until you drown in indirections, that are impossible to keep track of.
- zakirullin 1y agoIt seems like some engineers have emotional attachment to all these layered architectures. Explaining or giving them examples of failed projects (based on this architecture) doesn't help.
- andix 1y agoCargo cults
- shakesbeard 1y agoWe've only made good experiences with layered architecture (onion architecture in particular, which is quite straight forward). We also never built it with the idea in mind to ever replace the storage engine. No, the big, big benefit has been that we can test everything without ever mocking a single class. I also don't get the point about "going back to IoC" ... how is that mutually exclusive from using a layered architecture. This section was weird and didn't offer any good alternative.
- dope9967 1y agoFeels like the author completely misunderstood at least one of the fundamental and basic concepts of DDD - writing how it is only about the problem and not the solution space, where it is actually very clearly about both - but still decided to write down a very sure judgement of it. Disappointing.
- kadutskyi 1y agoTidy first? book gives lots of such advice. Very helpful.
- physidev 1y agoI think the viewpoint articulated in this post fits quite well with the one expressed in the often-shared "Programming as Theory-building" article (I think it was shared here just a few days ago). Scientists, mathematicians, and software engineers are all really doing similar things: they want to understand something, be it a physical system, an abstract mathematical object, or a computer program. Then, they use some sort of language to describe that understanding, be it casual speech, formal mathematical rigor, scientific jargon -- or even code. In fact, thinking about it, the code specifying a program is just a human-readable description (or "theory", perhaps) of the behavior of that program, precise and rigorous enough that a computer can convert the understanding embodied in that code into that actual behavior. But, crucially, it's human readable: the reason we don't program in machine code is to maximize our and other people's understanding of what exactly the program (or system) does. From this perspective, when we write code, articles, etc., we should be highly focused on whether our intended audience would even understand what we are writing (at least, in the way that we, the writer, seem to). Thinking about cognitive load seems to be good, because it recognizes this ultimate objective. On the other hand, principles like DRY -- at least when divorced from their original context -- don't seem to implicitly recognize this goal, which is why they can seem unsatisfactory (to me at least). Why shouldn't I repeat myself? Sometimes it is better to repeat myself!? When should I repeat myself?? If you want to see an example of a fabulous mathematician expressing the same ideas in his field (with much better understanding and clarity than I could ever hope to achieve), I highly recommend Bill Thurston's article "On proof and progress in mathematics" <https://arxiv.org/abs/math/9404236 https://arxiv.org/abs/math/9404236>.
- insanebrain 1y agoI love love love monorepo + fat encapsulated modules + a couple of deployables. Why does the software industry create fake complexity/creativity in the craft? Fashion/hype architectures for dopamine and fulfilment. You're just wasting energy finding new ways to create machine code for hardware. Why not get creative in the hardware and actually make something new? Another thing that really grinds my gears, is how many human hours are poured into js frameworks instead of improving browsers. What an utter waste of time. Maybe mediocre engineers like me who could never design a CPU or extend a browser need to feel seen by embracing a new domain whatever concept to make us feel warm and fuzzy but not really innovate the real hard things that move the needle.
- zakirullin 1y agoAgreed on every point! From what I observed, some engineers try to express themselves through exciting architectures. They are proud of it, they get their dopamine. Their craft can't be simple, if it is simple then they are dull too. At some point in time some of them stop associating their code with themselves, and take somewhat business approach. Most of them do not pass this point, unfortunately.
- zakirullin 1y agoI also find JS and all the infrastructure very mentally taxing. Building a legacy project via some esoteric and already out-of-fashion build system is so painful. Thousands of dependencies, hundreds of issues and warnings...
- gtzi 1y agoThis is also a proper framework for evaluating AI replies – they do not only need to be appropriate, they also need to consume the minimum cognitive load for parsing.
- computerdork 1y agoI completely agree with every in this article, but seems like it's just at different way of looking at the well-known software-engineering concept of "complexity." Yeah, the main difference is cognitive load is considering the complication of the system from how it effects the developer, while complexity focuses on the amount of complications in the system itself. Yeah, if you go through this article and replace most of the places where it mentions "cognitive load" with "complexity," it still makes sense. Yeah, this isn't a criticism of the article - In fact, there are important difference, like having more of a focus on what the dev is experiencing handling the complications of the system - But for those really interested in its concept, may want to learn about complexity too, as there is a lot of great info on this.
- sltr 1y agoAny discussion of cognitive load in programming needs to include awareness of this book: The Programmer's Brain: What every programmer needs to know about cognition. By Felienne Hermans https://www.manning.com/books/the-programmers-brain https://www.manning.com/books/the-programmers-brain
- neonrider 1y agoLove it. Make code accessibility a first-class citizen. Turn the rule books and their principles into guidelines. A smart coder knows to follow rules. A master knows code is meant to be read and develops contextual awareness for when and why to break a rule, or augment it, as the case may be. So, reintroduce judgment and critical thinking in your coding practice. Develop an intuitive feel for the cognitive costs and trade-offs of your decisions. Whether you choose to duplicate or abstract, think of the next person (who sometimes is you in six months). For those asking why author doesn't come up with their own new rules that can then be followed, this would just be trading a problem for the same problem. Absentmindedly following rules. Writing accessible code, past a few basic guidelines, becomes tacit knowledge. If you write and read code, you'll learn to love some and hate some. You'll also develop a feel for heavy handedness. Author said it best: > It's not imagined, it's there and we can feel it. We can feel it. Yes, having to make decisions while coding is an uncomfortable freedom. It requires you to be present. But you can get used to it if you try.
- zakirullin 1y agoThanks a lot! You've nailed it :)
- rhameetman 1y ago> Make code accessibility a first-class citizen. This is a good article but the main thing that bugs me about it is that the author completely disregards germane overhead. Germane overhead is about recognition and practice and, at scale, it matters just as much. Intrinsic and extraneous overhead is about the information itself and how it’s presented. Germane overhead is about the receiver so in order to make code accessibility a first-class citizen you can’t ignore it.
- PandaRider 1y agoThis is correct. To delve into a topic about cognitive load without talking about germane overhead disqualifies this article (i.e. similar to extraneous overhead in terms of effort but germane overhead is beneficial. Because it helps the coder's reading ability.) The examples are good but every reader must not have the takeaway that every effortful code is bad (e.g. haskell is extremely hard to read at first but every developer swears it has very high intrinsic cognitive load)
- exclipy 1y agoThis was my main takeaway from A Philosophy Of Software Design by John Ousterhout. It is the best book on this subject and I recommend it to every software developer. Basically, you should aim to minimise complexity in software design, but importantly, complexity is defined as "how difficult is it to make changes to it". "How difficult" is largely determined by the amount of cognitive load necessary to understand it.
- zakirullin 1y agoThat's best book on the topic! The article was inspired by this exact book. And John is a very good person, we discussed a thing or two about the article.
- exclipy 1y agoOh! I was surprised you didn't link or mention the book
- zakirullin 1y agoIt is mentioned/quoted in Deep Modules section: https://github.com/zakirullin/cognitive-load?tab=readme-ov-file#too-many-small-methods-classes-or-modules https://github.com/zakirullin/cognitive-load?tab=readme-ov-f... Maybe I should make it more visible.
- bsenftner 1y agoWhich is why I consider DRY (Don't Repeat Yourself) to be an anti-rule until an application is fairly well understood and multiple versions exist. DO repeat yourself, and do not create some smart version of what you think the problem is before you're attempting the 3rd version. Version 1 is how you figure out the problem space, version 2 is how you figure out your solution as a maintainable dynamic thing within a changing tech landscape, and version 3 is when DRY is look at for the first time for that application.
- hinkley 1y ago
- paxcoder 1y ago[dead]
- shaimagz 1y agoI’m not reading code anymore, cursor does
- alphazard 1y agoThe bit about "smart developer quirks" looks suspiciously like the author only understands code that they have written, or is in a specific style that they recognize. That's not the biggest driver behind cognitive load. Reducing cognitive load comes from the code that you don't have to read. Boundaries between components with strong guarantees let you reason about a large amount of code without ever reading it. Making a change (which the article uses as a benchmark) is done in terms of these clear APIs instead of with all the degrees of freedom available in the codebase. If you are using small crisp API boundaries to break up the system, "smart developer quirks" don't really matter very much. They are visible in the volume, but not in the surface area.
- hinkley 1y agoI learned pretty early on that people get really tired of optimization of code that is directly in the call stack they have to breakpoint in. Later on I clocked some of that as code smells pulling attention and analysis time during debug work. But the trick I found is that if you can extract a function for only the part of the code you’re optimizing/improving, and then make your change in a single commit, two things happen. One, it’s off the code path, so out of site, out of mind. Two, people are more forgiving of code changes they don’t like but can roll back by reverting a single commit. That breaks down a bit with PRs, since they tend to think of the code as a single commit. But the crisp boundaries still matter a lot.
- srcreigh 1y agoWhat do you mean about “people get really tired of optimization of code that is directly in the call stack they have to breakpoint in”? What’s the context where everybody else is using breakpoints?
- nycdotnet 1y agoIn some software platforms, the tooling makes it really easy to use a debugger to see what’s happening, so it’s common for everyone on the team to use them all the time. The comment you’re responding to mentioned pulling code into a function. As an example, if there’s a clever algorithm or technique that optimizes a particular calculation, it’s fine to write code more for the machine to be fast than the human to read as long as it’s tidy in a function that a dev using a debugger can just step over or out of.
- hinkley 1y agoCognitive load may be the dominant form of stress but it is not the only one. I feel like this is very close to correct but subtlety and critically broken. In particular, when the shit hits the fan, your max cognitive load tanks. Something people who grumble at the amount of foolproofing I prefer often only discover in a crisis. Because they’re used to looking at something the way they look at it while sipping their second coffee of the day. Not when the servers are down and customers are calling angry. You’ll note that we only see how the control room at NASA functions in movies and TV when there’s a massive crisis going on, or intrigue. Because the rest of the time it’s so fucking boring nobody would watch it.
- zkmon 1y agoChildren were always told to cram as much as possible into their memory. It was even claimed that, more you put into memory, you mind works better. Not quite. Human mind has evolved to interpret the sensory data collected by senses, and cause necessary action. Some of that interpretation uses memory to correlate the perceived data with the memory data. That's pretty much it. Overloading the human memory with tons of data which is not related to the context in which the person lives, can cause negative effects. I suspect it can also cause faster aging. New experiences, new information is like scales on a tree trunk. As you accumulate more of it, you age more.
- hinkley 1y agoI love learning and until recently despised teaching. I felt like a double agent nodding along at all the lies my teachers told me while I mastered the material almost in spite of the teaching instead of because of it. This became a real problem I college when the material was no longer a given. There were going to be people who flunked because the material was just too hard. I have always been a C+ student of rote memorization at best. Almost enough to be good at trivia, but not enough to do well in coursework. I am always trying to build a Theory of a System from practically word one, which is the fifth stage of learning, where rote is the first.
- scoofy 1y agoI always explain it this way: Balancing a cup on a tray isn't too hard. The skill comes in when you can balance 10 cups, and a tray on top of them, and then ten more cups, and another tray, and a vase on that... each step isn't difficult, but maintain the structure is difficult. It's like that, but with ideas.
- catchcatchcatch 1y ago[dead]
- stevage 1y agoA tip: if you're ever writing an article like this which is essentially do's and don'ts, adopt a consistent format for each. In many of these it's not immediately clear which is the do and which is the don't, creating, ironically, cognitive load for the reader.
- xiphmont 1y agoThis is actually some wonderful work that succinctly explains a lot of my experience. Much of how I was formally taught to program is counterproductive to the big picture the second someone else has to understand the code. It's part of the reason that I hate dealing with Rust and C++, and breathe a sigh of relief when the codebase I need to suck into my head is good old C. C offers fewer ways to hide all the working code in six layers of templates.
- zakirullin 1y agoNice to hear that it resonates with your experience. I liked C for the exact same reason. Switched to Golang recently, simplicity is cherished here too!
- ivanjermakov 1y ago> Let's say we have been asked to make some fixes to a completely unfamiliar project. How real is this use case? Unless you switch projects really often, this is like a week per two years. Perhaps we should focus on solving problems that are hard by nature, not by experience of a developer or other external factors.
- msephton 1y agoCurious why github is linked and not the blog post? https://minds.md/zakirullin/cognitive https://minds.md/zakirullin/cognitive
- deleted 1y ago[deleted]
- rkagerer 1y agoThese are good tips. A lot of it boils down to writing well-organized code geared for human consumption. Junior programmers too often make the mistake of thinking the code they write is intended for consumption by the machine. Coding is an exercise in communication. Either to your future self, or some other schmuck down the line who inherits your work. When I practice the craft, I want to make sure years down the line when I inevitably need to crack the code back open again, I'll understand what's going on. When you solve a problem, create a framework, build a system... there's context you construct in your head as you work the project or needle out the shape of the solution. Strive to clearly convey intent (with a minimum of cognitive load), and where things get more complicated, make it as painless as possible for the next person to take the context that was in your head and reconstruct it in their own. Taking the patterns in your brain and recreating them in someone else's brain is in fact the essence of communication. In practice, this could mean including meaningful inline comments or accompanying documentation (eg. approach summary, drawings, flowcharts, state change diagrams, etc). Whatever means you have to efficiently achieve that aim. If it helps, think of yourself as a teacher trying to teach a student how your invention works.
- ruszki 1y agoAs a coder, these are the exact problems which shouldn’t cause problems for you. You should be a coder because you’re better in these problems than others. More coders are needed, than to who these are “simple”, I understand. But, if you have problems with these, I would definitely try to pivot to something else, like managerial positions. Especially with AI on us. Of course, if you are fine to be an “organic robot”, then it’s fine, but you’ll never really get why this profession is awesome. You’ll never have the leverage.
- baazaa 1y agoI would just add the IsAllowed etc. as a comment next to the relevant line. Often the explanation is bigger than what you'd want in a variable name, I find it less overhead than making more variables, and it makes better use of screen-space. I'd only lean towards intermediate variables if a) there's lots of smaller conditionals being aggregated up into bigger conditionals which makes line-by-line comments insufficient or b) I'm reusing the same conditional a lot (this is mostly to draw the reader's attention to the fact that the condition is being re-used).
- neehao 1y agoThis article covers a lot of the points: https://www.gojiberries.io/building-together-separately-challenges-of-software-development/ https://www.gojiberries.io/building-together-separately-chal... "A single page on Doordash can make upward of 1000 gRPC calls (see the interview). For many engineers, upward of a thousand network calls nicely illustrate the chaos and inefficiency unleashed by microservices. Engineers implicitly diff 1000+ gRPC calls with the orders of magnitude fewer calls made by a system designed by an architect looking at the problem afresh today. A 1000+ gRPC calls also seem like a perfect recipe for blowing up latency. There are more items in the debit column. Microservices can also increase the costs of monitoring, debugging, and deployment (and hence cause greater downtime and worse performance)."
- nige123 1y agoToo much cognitive load is a flow stopper. Finding flow while coding is a juggling act to keep things in the Goldilocks zone: not too hard, not too easy. This is tricky on an individual level and even trickier for a team / project. Coding is communicating how to solve a problem to yourself, your team, stakeholders and lastly the computer. The Empathic Programmer?
- bambax 1y agoCognitive load is an important concept in aviation. It is linked to the number of tasks to run and the number of parameters to monitor, but it can be greatly reduced by training. Things you know inside and out don't seem to consume as much working memory. So in software development there may be an argument to always structure projects the same way. Standards are good — even when they're bad! because one of their main benefit is familiarity.
- Szpadel 1y agoI would say that's very important rule. We have lots of projects using framework dependent magic, lots of useless interfaces and factories that give only theoretical value, magic that patch other classes methods etcz but this is standard practice in this framework and all experienced developers know that. by doing something better here would actually not bring any value, because it would mean that developers would have to remember that this one thing is done differently. that's trap where I would say many mid Devs fall in, they learned how do things better, but increase congnitive load for the rest of developers just by doing things differently.
- TZubiri 1y agoAn important difference is that the aviator would be the user of the airplane system. OP is talking about the cognitive load of the plane engineer. It's an important distinction in terms of priorities. I personally think the experience of the user is orders of magnitude more important than engineer cognitive load.
- schnatterer 1y ago> business logic and http status codes Why hold this custom mapping in our working memory? It's better to abstract away your business details from the HTTP transfer protocol, and return self-descriptive codes directly in the response body: { "code": "jwt_has_expired" } While the logic behind it sounds reasonable, REST does the exact opposite with the same goal: simplicity, easy to learn, i.e. reduce mental load. I know there are other reasons for REST/SOAP/Graphql, etc. Still makes mental load a somewhat subjective matter to me.
- hn_throwaway_99 1y agoIn my experience, though, a lot of "REST in the real world" failed at its lofty original goals, precisely because its original goals required too much cognitive load. The reason REST largely succeeded (or, rather, what I like to refer to as "REST-lite") is because people who wanted to build stuff quickly on the web realized "Hey, I don't need all this protocol complexity (see: SOAP), I can just make simple, human-readable API calls over the same HTTP layer my browser uses anyway". There is other stuff in "official REST" that I think has some value, like the noun/verb structure of API routes, but shoehorning API-level error codes into HTTP status codes has been a disaster IMO. Every time I've seen this done I've seen the same issues come up again and again and new developers constantly have to rediscover solutions and problem spots. Does "404" mean the API endpoint doesn't exist, or that particular resource doesn't exist? How do I map my very specific API error to rather generic HTTP status codes? Does a status code error mean a problem with the networking or the application?
- Too 1y agoThe article misses that http status code is not a custom mapping, it’s a standard mapping. Using this standard, most http libraries will already be equipped with features to handle them, for example automated retries and backoffs on a 429 with Retry-After. Replacing this standard with custom strings in the response body is terrible advice. Even if we all could have wished that http status codes should have been human readable strings rather than numbers. Augmenting the standard response with additional custom information is still something you can and should do as cherry on the top, or if you have many conditions falling under the same standard code. Like, don’t shoehorn something custom into 418 I’m a teapot just because it happened to be unused.
- asimovfan 1y agoI don't seem to come across such limits when i am doing something i am not supposed to be doing (procrastinating, for example obsessively reading something other than what i should be reading).
- 0xbadcafebee 1y ago> We need something more fundamental, something that can't be wrong. What is this bug in software people's brains that keeps thinking "I can come up with a perfect idea that is never wrong" ? Can a psychologist explain this to me please? Like, scientists know this is dumb. The only way something can be perceived as right, scientifically, is if lots of people independently test an idea, over and over and over and over again, and get the same result. And even then, they just say it's true so far. But software people over here like "If I spend 15 minutes thinking about an idea, I can come up with a fundamental principle of everything that is always true forever." And sadly the whole "fundamental principle" is based in ignorance. Somebody heard an interesting-sounding term, never actually learned what it meant, but decided to make up their own meaning for it, and find anything else in their sphere (software) that backs up their theory. If they'd at least quoted any of the academic study and research about cognitive load over the past 35 years, maybe I might be blowing this out of proportion? But nope. This is literally just a clickbait rant, based on vibes, backed up by quotes from blogs. The author doesn't seem to understand cognitive load at all, and their descriptions of what it is, and what you should do in relation to it, are all wrong. The article doesn't even mention all three types of cognitive load. And one of the latest papers on the subject (Orru G., Longo L. (2019)) basically came to the conclusion that 1) the whole thing is very complex, and 2) all the previous research might be bunk or at least need brand new measurement methods, so... why is anyone taking this all as if it's fact? But I'm not really bothered by the ignorance. It's the ego that kills me. The idea that these random people who know nothing about a subject are rushing to debate this, as if this idea, or these people's contributions, have merit, just because they think they're really smart.
- jakubdudek 1y agoUnless you have a quad-core brain like me and can vibecode four separate parts of the project in four terminal tabs. Of course, using your own method. Just kidding, of course.
- gblargg 1y ago"Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?" -- Brian Kernighan
- defanor 1y agoI think most programmers agree that simpler solutions (generally matching "lower cognitive load") are preferred, but the disagreements start about which ones are simpler: often a lower cognitive load comes with approaches one is more used to, or familiar with; when the mental models one has match those in the code. For instance, the article itself suggests to use early/premature returns, while they are sometimes compared to "goto", making the control flow less obvious/predictable (as paxcoder mentioned here). Intermediate variables, just as small functions, can easily complicate reading of the code (in the example from the article, one would have to look up what "isSecure" means, while "(condition4 && !condition5)" would have shown it at once, and an "is secure" comment could be used to assist skimming). As for HTTP codes, those are standardized and not dependent on the content, unlike custom JSON codes: most developers working with HTTP would recognize those without additional documentation. And it goes on and on: people view different things as good practices and being simpler, depending (at least in part) on their backgrounds. If one considers simplicity, perhaps it is best to also consider it as subjective, taking into account to whom it is supposed to look simple. I think sometimes we try to view "simple" as something more objective than "easy", but unless it is actually measured with something like Kolmogorov complexity, the objectivity does not seem to be there.
- brucehoult 1y ago> For instance, the article itself suggests to use early/premature returns I like premature returns and think they reduce complexity, but as exclipy writes (I think quoting Ousterhout) 'complexity is defined as "how difficult is it to make changes to it"'. If premature returns are the only premature exit your language has then they add complexity in that you can't then add code (in just one place) that is always executed before returning. A good language will also have "break" from any block of code, such that the break can also carry a return value, AND the break can be from any number of nested blocks, which would generally mean that blocks can be labelled / named. And also of course that any block can have a return value. So you don't actually need a distinguished "return" but only a "break" that can be from the main block of the function. A nice way to do this is the "exit function", especially if the exit function is a first class value and can also exit from called functions. (of course they need to be in a nested scope or have the exit function passed to them somehow). It is also nice to allow each block to have a "cleanup" section, so that adding an action to happen on every exit doesn't require wrapping the block in another block, but this is just a convenience, not a necessity. Note that this is quite different to exception handling try / catch / finally (Java terms) though it can be used to implement exception handling.
- shreddit 1y agoDon't agree with "Business logic and HTTP status codes" tbh, because now i have to work with apis that do this: Statuscode: 200 { success: false, error: "..." }
- Culonavirus 1y agoI don't really care either way, it's not a big issue to me, but I can see why people might do that. I mean what if an api endpoint returns a 403 when the end user doesn't have access to that resource, but also 403 because you, the consumer/app doesn't have access to the "server" the api is running on? HTTP codes were originally intended as server status codes, not server application status codes. At least with 200 you know your request was processed on the server successfully.
- Izkata 1y agoAlso, apache ignores the content body and returns an empty string with several classes of error codes, so using 200 is the only reliable way when you want to get that custom error message to the user.
- ppsreejith 1y agoA lot of comments mention John Ousterhout's book Philosophy of software design and it's definition of complexity of a system being cognitive load (I.e the number of disparate things one has to keep in mind when making a change). However IIRC from the book, complexity of a system = Cognitive load * Frequency of change. The second component, frequency of change is equally important as when faced with tradeoffs, we can push high cognitive load to components edited less frequently (eg: lower down the stack) in exchange for lower cognitive load in the most frequently edited components.
- deleted 1y ago[deleted]
- hollowturtle 1y agoLike another user said it depends on each developer background what's simpler and what's not. For example I have a problem with intermediate variables for improving readability, like isAllowed, it really is more readable but more often than not in large codebases what the name implies is not what the conditional check is or it is but it's not exaustive. So i have to inspect the variable to see what it actually is. The thing is that comments and variable names must be maintained as well as code, so it implies a certain degree of cognitive load to maintain. While a conditional like (condition2 || condition3) looks bad it still is more straightforward
- austin-cheney 1y agoPeople can argue about this all day, but one thing is always crystal clear. Simplicity comes from practice writing and refactoring large code thousands of times. People with limited or shallow experience may think they are good at this but only when they isolate themselves to known patterns of comfort or some giant framework. There is a lot of insecurity there. Super experienced people, that is people with lots of practice writing large original applications, don’t think like the pretenders. Simplicity is built in like muscle memory. They just solve fucking problem and go drink a beer. There is no memorized pattern nonsense. The super experienced developers see the pretenders for what they are while the pretenders either can’t see the distinction or just feel hostility at the deviation far outside a memorized convention.
- hackrmn 1y agoIn my experience, writing readable code and writing code that behaves correctly (fulfills the contract/requirements without hiding potential faults) is often mutually exclusive -- most people end up doing one or the other. This is related to the never-ending functional programming vs. "traditional programming" (a target in motion, largely OOP or in the very least "whatever is taught at the graduate schools"), since the former, in contrast to the article which pretty much _assumes_ the latter, doesn't even facilitate "variables", literally or in informal sense (things you can "assign to", whether changing or not). Anyway, I happen to belong in the latter category according to most -- the longer I have been doing this, the more I lean into the purely functional style, almost mathematical vigor, because I have learned how much (or rather little) margin there is to introduce subtle errors once you have actual _variables_ that may change freely, which start to encourage you to do other things which in the end contribute to lack of correctness, readable or not. Now, you may blame people like me, and I cannot blame you for not having the cognitive load capacity to understand some of the code I write "succinctly", but my point is that for all the merit of the article (yes, I agree code is read much more often than it is written, lending value to the "readability" argument), it doesn't acknowledge the fact readability and correctness are _in practice_ often mutually exclusive. Like, in the field. Because I wager that the tendency is to approach a more mathematical expression style as one becomes better at designing software, with adversarial conditions manifesting in terms of bugs hiding in mutability of state and large, if "simple", bodies of functions, classes (which have methods you cannot guarantee to not mutate the object's state). We need to find means to write code that is readable but without compromising other factors like mutability which _too_ has been shown to compromise correctness. What good is readable software that never manages to escape the vortex of issues, driving the perpetually busy industry "fixing bugs". At my place of work, I obviously see both kinds of the "mutually exclusive", and I can tell you without due pride and yet with good confidence, people who write readable code -- consisting of aliasing otherwise complex expression with eloquently named variables (or sometimes even "constants", bless their heart), and designing clumsy class hierarchies -- spend a lot of subsequent effort never being able to be "done" with the code, and I don't mean just because requirements keep changing, no -- they sit and essentially "fixup commit" to the code they write, in perpetuity, seemingly. And we have select few who'd write a code-base with as few variables as possible, with a lot of pure function -- what I referred to as "mathematical programming" in a way -- and I never hear from them much offering "PRs" to fix their earlier mishaps. The message that sends me is pretty clear. So yeah, by all means, let's find ways to write code our fellow man can understand, but the article glosses over a factor that is at least as important -- all the mutability and care for "cognitive load" capacity (which _may be_ lower for current generation of software engineers vs earlier ones) may be keeping us in the rotating vortex of bugs we so "proudly" crouch over as we pretend we are "busy". I, for one, prefer to write code that works right from get-go, and not have to come back to said code unless the requirements which made me write it the way I did, change. On a very rare occasion, admittedly, I have to sacrifice readability for correctness, not because it's inherently one or the other, but because I too haven't yet found the perfect means to always have both, and yet correctness is on the absolute top of my list, and I advocate that it should be on top of your as well, dare I to say so. But that is me -- perhaps I set the bar too high?
- ksec 1y agoI think this just describe why people procrastinate.
- itsafarqueue 1y agoDon’t bother with this if you want to get promoted. Others have discussed this in thread and are right. If you build beautiful, simplified abstractions, your skill will be taken for granted as these interfaces appear obvious once discovered (by virtue of their proximity to truth, incredibly difficult to create, easy to verify). If you are in even a reasonably large org, go the other way. Be an Architecture astronaut. Build complex, clever stuff that is deliberately high cognitive load. Get your bus-factor as close to one as possible. Go the other way only if your comp is directly tied to company performance.
- ttz 1y agoIt hurts because it's true The amount of staffs at my place who build pointlessly complex bullshit that doesn't actually do anything different is too damn high
- baalimago 1y agoHey, OP, stop bashing on functional languages..!
- baalimago 1y agoThe same principle applies within context engineering
- mleonhard 1y ago> There is no “simplifying force” acting on the code base other than deliberate choices that you make. Simplifying takes effort, and people are too often in a hurry. There is a simplifying force: the engineers on the project who care about long-term productivity. Work to simplify the code is rarely tracked or rewarded, which is a problem across our industry. Most codebases I've worked in had some large low-hanging-fruit for increasing team productivity, but it's hard to show the impact of that work so it never gets done. We need an objective metric of codebase cognitive complexity. Then folks can take credit for making the number go down.
- about3fitty 1y agoCognitive load is super important and should be optimised for. We all should have as our primary objective the taming of complexity. I was surprised to find an anti-framework, anti-layering perspective here. The author makes good points: it’s costly to learn a framework, costly to break out of its established patterns, and costly when we tightly couple to a framework’s internals. But the opposite is also true. Learning a framework may help speed up development overall, with developers leaning on previous work. Well designed frameworks make things easy to migrate, if they are expressive enough and well abstracted. Frameworks prevent bad and non-idiomatic design choices and make things clear to any new coder who is familiar with the framework. They prevent a lot of glue, bad abstractions, cleverness, and non-performant code. Layering has an indirection cost which did not appeal to me at all as a less experienced developer, but I’ve learnt to appreciate a little layering because it helps make predictable where to look to find the source of a bug. I find it saves time because the system has predictable places for business logic, serialisation, data models, etc.
- leric 1y ago[dead]
- hannhadeill2 1y ago[dead]
- johnlinnes32 1y ago[flagged]
- perlische65 1y ago[dead]
- nathane280 1y agobrb adding this to my CLAUDE.md
- nathane280 1y agoFor the lazy: ### Reduce Cognitive Load By: *1. Simplify Conditionals* ``` // High cognitive load if val > someConstant && (condition2 || condition3) && (condition4 && !condition5) // Low cognitive load isValid = val > someConstant isAllowed = condition2 || condition3 isSecure = condition4 && !condition5 if isValid && isAllowed && isSecure ``` *2. Use Early Returns* ``` // Nested ifs if isValid { if isSecure { doStuff() } } // Early returns if !isValid { return } if !isSecure { return } doStuff() // Happy path is clear ``` *3. Prefer Deep Modules* - *Deep module*: Simple interface, complex implementation (e.g., UNIX I/O with 5 methods) - *Shallow module*: Complex interface for simple functionality - Few deep classes > Many shallow classes *4. Use Self-Describing Values* ``` // Numeric codes requiring mental mapping 401 // expired token? 403 // insufficient access? // Self-describing { "code": "jwt_has_expired" } ``` *5. Apply DRY Carefully* - Don't create abstractions too early - Avoid tight coupling between unrelated components ### Avoid These Anti-Patterns: *1. Inheritance Chains* ``` AdminController extends UserController extends GuestController extends BaseController Use composition instead ``` *2. Too Many Layers* - Unnecessary abstraction layers add indirection, not simplicity - Only add abstractions when you need actual need to *3. Framework Magic* - Keep business logic framework-agnostic - Use frameworks as libraries, not containers for your logic - New developers shouldn't need months to learn framework "magic"
- diegobit 1y agoI think these books and resources should not be viewed as hard rules, but as sets of examples explaining guiding principles, and the internet is full of discussions that turn into religious wars over it. It is always worth it for a programmer to dwell over what complexity is according to Osterhaur; it is worth it to reason over what Uncle Bob thinks is "clean" code, etc. I'm not benefiting from either by applying what they say dogmatically, but I improve my taste in what is good software to me, by discovering and trying many approaches. Without reading them I might never even have thought at a particular solution, or a particular frame of mind.
- anandgoel65 1y ago[dead]
- anandgoel65 1y ago[dead]
- artur_makly 1y agoIs it possible to have a system prompt for an LLM to follow some of these best practices? Has anyone made a reduced system prompt with these principles?
- tooheavy 1y ago[dead]