12 ms·
Cognitive loads in programming
- troelsSteegin 4y agoWould GOMS [0] be a useful framework for thinking about cognitive load in programming? GOMS is a framework for analyzing user workload in system interaction. Bad or gnarly code creates a much more complex interface for the programmer. A quick look did not surface a reference here, but I'd look further at work by David Kieras [1]. [0] https://en.wikipedia.org/wiki/GOMS https://en.wikipedia.org/wiki/GOMS [1] https://www.researchgate.net/profile/David-Kieras https://www.researchgate.net/profile/David-Kieras
- Lwepz 4y agoSplendid article. I was thinking that perhaps walking the readers of our code through our architectural decisions(and not just through what our code does) is a good way to lessen their cognitive load. This helps identify decisions that have been taken to look smart or because the foie-gras the author ate on that day went down really well with the Chardonnay and made them feel extra stylish. This also helps us understand how well we know the tools we're using versus how much we do simply through pattern repetition.
- ABS 4y agoit's going to take quite some time to read it all since it's long and deserves the time but since it's soliciting early feedback here it is: research and quote all the works done over the last 10 or so years by others in this space!! The topic of cognitive load in software development is far from rarely considered and in fact it's been somewhat "popular" for several years depending on what communities and circles you participate it on- and off-line. I'm surprised not to find any mentions to things like: - the Team Topologies book by Skelton and Pais, published in 2019 where they cover the topic. Particularly of note here is the fact that Skelton has a Computer Science BSc and a Neuroscience MSc - the many, many, many articles, posts, discussions and conference sessions on congnitive load from the same authors and connected people in subsequent years (I'd say 2021 was a particularly rich year for the topic) - Dan North sessions, articles and posts from around 2013/2014 in which he talks about code that fits in your head but no more, referencing James Lewis original... insight. E.g. his GOTO 2014 session "Kicking the Complexity Habit" https://www.youtube.com/watch?v=XqgwHXsQA1g&t=510s https://www.youtube.com/watch?v=XqgwHXsQA1g&t=510s a quick search returns references to it even in articles from 2020 https://martinfowler.com/articles/class-too-large.html https://martinfowler.com/articles/class-too-large.html - Rich Hickey's famous 2011 Simple Made Easy talk https://www.infoq.com/presentations/Simple-Made-Easy/ https://www.infoq.com/presentations/Simple-Made-Easy/
- Lwepz 4y ago>research and quote all the works done over the last 10 years or so by researchers in this space!! I totally understand your point and appreciate you linking those resources, however I think it's important to remember that the author's post is from a personal blog, not from a scientific journal or arxiv. Perhaps OP would've never posted this if he felt that his "contribution" wasn't novel enough. Additionally, there's a chance that the wording and tone the author used might speak to people who found the articles you mentioned opaque(and vice versa, obviously). If the author, feeling the urge to write something up, had looked very hard for "prior work" instead of following the flow of their insights gained through experience, perhaps they would've felt compelled to use the same vocabulary as the source, which has its pros(forwarding instead of reinventing knowledge) and cons(propagating opaque terms, self censoring because of a feeling of incompetence in the face of the almighty researchers). That's one of the great things about blog posts: to be able to write freely without being blamed for incompleteness or prior art omission. On a different note, I think this may also highlight the fact that the prior work you mentioned isn't easy enough to find. Perhaps knowledge isn't circulating well enough outside of particular circles.
- rpeszek 4y agoAbout "Cognitive load being rarely considered", I meant it in actual project work, not in the sense that the idea of applying cognitive psychology to programming is new. I am sure the topic has been considered in an academic setting. I would not feel qualified to provide a good reading list on the topic. This is also related to code quality, thus it will have a ton of relevant work. Thank you for the links, in particular to Skelton, Pais, I will have a look!
- UweSchmidt 4y agoOne measure for code quality should be the effort to make a minor change to code, or to fix a simple, common bug. Can a developer who is familiar with the code, effortless make a change in an area where change was expected at the beginning? Assuming a typical, minor bug that turns out to originate from the usual suspect places in the code (database query, logical error, incomplete implementation of a requirement, off-by-one/calculation error). Is it usually easy to narrow things down, and to spot the error? That means the lead architect should regularly try implementing minor features or fix minor bugs and/or pair up with colleagues who do, and draw conclusions about the code accordingly.
- hu3 4y agoThat's a good one. Another measure I use for code quality is: how afraid am I of breaking something when I make changes? This is where typing and tests shine.
- wtetzner 4y agoTyping and tests definitely help, but nothing works better than having well-factored, decoupled code, so a change in one place doesn’t impact the rest of the code base in unexpected ways. Unfortunately I don’t know of a good way to do that outside of experience + vigilance.
- baby 4y agoGood abstractions + asserts + minimal assumptions everywhere in the code (also called refactoring-resistant code)
- deleted 4y ago[deleted]
- bcrosby95 4y agoUnexpected is an interesting word. This probably means consistency is important, because expected in one codebase could be unexpected in another.
- mikewarot 4y agoI tend to think of this as an impedance matching[1] (in the EE sense) problem. The best frameworks match the way we think about problems once we've gotten used to them. There has to be some give on the part of the programmer, because of Godel's incompleteness theorems.[2] I whole heartedly agree that we have to minimize extra steps when reviewing code, but you can only push so much of that burden back through space-time to the green field programmer. For instance, in Pascal, you have to declare everything first. I'm used to that, so it matches my expectations. However, it also sucks because if you're looking in the middle of code the declarations aren't proximal to the first time they're used. There's an expectation that all the code will be read, which was fine in the academic world which gave birth to Pascal, but not in the world of million line systems. There are tradeoffs that will take decades to get right, simply because we need to have time to gain enough perspective to adjust things collectively, as a profession. [Edit -- Tweak link format per suggestions below] [1] - https://en.wikipedia.org/wiki/Impedance_matching https://en.wikipedia.org/wiki/Impedance_matching [2] - https://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_theorems https://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_... [3] - https://en.wikipedia.org/wiki/Off-by-one_error https://en.wikipedia.org/wiki/Off-by-one_error
- Jtsummers 4y agoIs there a reason you deliberately make it hard for people to follow the links you put in your comments?
- mikewarot 4y agoI number them, and space them out to make it easy to select and copy... there's no way to inline hyperlinks here that I'm aware of. Option #1 -- formatted as a code block [1] - https://en.wikipedia.org/wiki/Impedance_matching [2] - https://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_theorems [3] - https://en.wikipedia.org/wiki/Off-by-one_error Option 2 -- jumble of links [1] - https://en.wikipedia.org/wiki/Impedance_matching https://en.wikipedia.org/wiki/Impedance_matching [2] - https://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_theorems https://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_... [3] - https://en.wikipedia.org/wiki/Off-by-one_error https://en.wikipedia.org/wiki/Off-by-one_error - Option 3 -- Extra line breaks everywhere [1] - https://en.wikipedia.org/wiki/Impedance_matching https://en.wikipedia.org/wiki/Impedance_matching [2] - https://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_theorems https://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_... [3] - https://en.wikipedia.org/wiki/Off-by-one_error https://en.wikipedia.org/wiki/Off-by-one_error - None of those really seems right [Edit] Sorry, I didn't know about the issues on mobile. it definitely wasn't trying to make it worse on purpose. I added the off by one link to make the examples long enough The 2 biggest problems in computing... Naming things, Cache Invalidation, and off by 1 errors.
- giantg2 4y agoMultiple levels of abstraction kills me, at least without adequate documentation. Conceptually, it's veey easy to grasp, but in code it becomes a mess making jumps through multiple unfamiliar files in a large code base. Essentially, you end up having to hold all the pertinent information on that code in your head, which largely defeats some of the purposes of breaking them into multiple files.
- baby 4y agoYou’d probably say the same if no abstractions were there. It’s a trade off. Don’t necessarily abstract something, but do it if it makes everything else better and more maintainable and more secure. Probably a good philosophy is to never start with abstraction and leave that to refactors.
- giantg2 4y agoYeah, we seem to have gotten better at this by using noSQL databases with one big JSON object for each item instead of relational based on OOP objects.
- BigJono 4y agoOne problem that's usually missed with these kinds of "black!", "no, white!" comment chains is that people are working in different environments with completely different points of reference to work from. Front-end developers hear "no abstractions is bad!", and they don't take into account that something like React already provides an abstraction more powerful than all the abstractions put together in some other programming environments. Having a localised section of UI bundled with everything driving it in a single 20 line file is absolute light years ahead of the dumpster fire of the 2010 web, which in turn was probably light years ahead of whatever people were doing with IE and Netscape in the 90s. So they do crap like separate into "logic" and "display" components, or they import 6 heavily abstracted libraries on top that give virtually no additional benefit and just add 8,000 lines of third party documentation to the already heavy cognitive burden other developers on the project have to understand the code. Likewise even though I've never worked on one, I'm sure there's projects in more 'low level' environments where a single good functional abstraction could wipe out 200 lines of code in a flash, and the 3rd party libraries available are actual huge upgrades. If that's all you've ever worked on and you hear an (actual good) front end dev completely shithouse 3rd party libraries you'll likewise be as terrified of their advice as I am when I hear people talk about something being underabstracted.
- baby 4y agoPeople write code for computers, but they should also write code for humans. Humans have different parsers and the evolution of the code is dictated by how quickly and efficiently can these human parse the code.
- karmakaze 4y agoI write code for humans, first of all me. Ensuring correctness, getting the syntax right, and following style conventions, etc is what follows. It's much easier for a human to verify the logic if it's easy to read and comprehend. Good notes in a pull-request is also handy and easy to find with a git-blame and commit hash lookup on GitHub.
- luciusdomitius 4y agoProgramming code is for humans. Machine code is for machines. The compiler translates from human to machine.
- deltasevennine 4y agoNbdy wrts lke ths 4 hmns so wy do we wrt lke ths for prgrming? I alwys c sht lke "CompPtr". What? Is tht a Computer or Complex Pointer? Wtf? Basically everyone agrees with you but when it comes time to name stuff all humans suddenly forget everything and think brevity is some sort of required part of naming in code.
- CraigJPerry 4y agoThis is an enjoyable read. The topic of abstraction needs to be explored more here. I wonder if the author would agree that In practice almost all abstractions can be made to leak. Given that, then even experienced developers who understand how to avoid mixing different layers of abstraction will seldom succeed in creating abstractions without leaks. If an abstraction leaks, it’s not germane, it’s incidental complexity. This applies to blueprints as equally as it does to implementations. The author notes the caveat in soundness of blueprints - not something a common developer can do much about - but if the developer designs blueprints with unintended behaviours - for example the author’s recursive let example - then they’re being very generous with the helpfulness of blueprints since they are no silver bullet to avoid shooting yourself in the foot. The common case in software development is not a PLT enthusiast. Blueprints are just another way you can shoot yourself in the foot if you hold the tool wrongly. And the common case is not to understand the tool much more than at a fairly superficial level, so mishandling is all but assured. This means pragmatically, there’s no substitute for an acceptable level of testing in a project.
- he0001 4y agoMy pet peeve with this, is that people write code that doesn’t reflect the problem. A messy problem should have a messy solution as that would reflect the problem. As soon you start to write code that’s either for the sake of something else, clean code etc, you deviate from what you are trying to solve. That creates a solution which hard to follow, as the problem is abstract and others may be able to interpret that. But then if you look at some code that does something entirely different, due to language constructs, framework or some diligent programmer trying to write good looking code but has nothing to do with the problem. That creates cognitive load as you need to not just only understand and solve original problem and changes, you need to understand the actual code too.
- atoav 4y agoI once wrote an extremely general and elegant piece of code for an extremely messy problem (some obscure CSV from a source system I cannot influence with a ton of inconsistencies and mistakes that I have to straighten out automatically). I started out with straightforward and somewhat messy code, but after adjusting that 3 times, I ended up writing something that is more or less a toolset to deal with the problems that data had. The code of the tools is convoluted, but when I have to adjust some things every now and then I just use the tools I built anyways so who cares. Abstraction in programming should be seen like certain devices, helpers etc. someone would make use of in woodworking. Of course it costs you some time to built them, but it can make your life a lot easier, because ot makes results more consistent and testable.
- layer8 4y agoYes, I would formulate this as the distance between the mental model of the functionality being implemented and the structure of the code. The interesting question is how to design programming languages, libraries and tooling so that gap remains small.
- michaelwww 4y ago> A messy problem should have a messy solution as that would reflect the problem I've never heard this expressed before and it goes against my experience. My entire goal is to find a simple solution to a messy problem. I can think of a lot of simple solutions to messy problems. If programming required me to come up with messy solutions to messy problems I wouldn't want to do it. Most programmers like that "a-ha" moment of a discovering a simple and elegant solution to a messy problem.
- wikitopian 4y agoAlan Kay is a very nice and bright guy and I don't want to hurt his feelings. But this is a perfectly soluble problem and it is entirely and exclusively Alan's fault that everybody stampeded in the wrong direction to our current situation.
- z9znz 4y ago> We ask “How long will it take?” That is the first problem. We should be asking several questions, and the value of their answers would be weighted against business goals. How long will it take? How will it affect future development (pace). How will it affect the forced total rewrite date (a broader view of the previous question). And my favorite, how difficult will it affect provability of system behavior? This point is greatly affected by frameworks which impose their own conventions (which change over time).
- prohobo 4y agoCompetent*
- keyle 4y agoOne 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.
- suzzer99 4y agoI must be weird because I love YAML. I love the brevity of no closing brackets and the finality of the indentation being the code, rather than just window dressing that can get out of whack.
- OneLessThing 4y agoIf we improve our programming languages and practices to make code bases more easily understood we will simply increase the scope of what the projects attempt to solve, not reduce their complexity. While this is a good for software it still means we’re going to be moaning about working on complex software. It’s like how the increased economic productivity due to technology has not made the work week shorter.
- luciusdomitius 4y agoThis is insanely good! I always thought I am the only person in the world taking that into account when designing/coding something.
- googlryas 4y agoI've often thought of this as "developer empathy" when I was working at Amazon. Generally regarding people who create APIs for other developers to use. The idea being that you can make your API simple or complex, and most developers tend to make their API complex, because they think their system is really powerful and cool and want to expose all the power to end users. But, you need to remember that your users aren't just using your API. They are using maybe 100 other ones as well. And there is no way for a person to learn the ins and outs of all 101 complex APIs. Add to this the fact that the more complexity you expose, the more unintentionally coupled your API becomes to your implementation (generally). So, make your APIs simple, and provide backdoors if you really want to expose complexity. I will say, this did not get me promoted at Amazon.
- jackblemming 4y agoThat just sounds like the designer didn't layer the API properly. A good API has a sensible top level that does all the common use cases, but also allows access to the lower level layers for power users.
- googlryas 4y agoWell, yes. I'm talking about API design, and what's good and what's bad. When you're dealing with microservice architecture in Amazon you deal with a whole lot of APIs.
- krawczstef 4y agoYes! As one of the creators of https://github.com/stitchfix/hamilton https://github.com/stitchfix/hamilton this was one of the aims. Simplifying the cognitive burden for those developing and managing data transforms over the course of years, and in particular for ones they didn't write! For example in Hamilton -- we force people to write "declarative functions" which then are stitched together to create a dataflow. E.g. example function -- my guess is that you can read and understand/guess what it does very easily. # in client_features.py @tag(owner='Data-Science', pii='False') @check_output(data_type=np.float64, range=(-5.0, 5.0), allow_nans=False) def height_zero_mean_unit_variance(height_zero_mean: pd.Series, height_std_dev: pd.Series) -> pd.Series: """Zero mean unit variance value of height""" return height_zero_mean / height_std_dev To use `height_zero_mean_unit_variance` somewhere else, you'd then find it as a parameter to some other function, and that's the basic gist of how you'd develop a dataflow. To then execute the dataflow, you'd then in a separate file, decoupled from your transform logic, write some code to (1) create the DAG, and then (2) request what you want executed from it. In terms of reducing cognitive burden for maintainers, by forcing things into a function there's all these nice properties to be had for maintenance: - unit testing is always possible - integration testing is super easy, since you can add code, and then _only_ test that path without having to run your entire transform workflow. - documentation has a natural place & and we can build a DAG visualizing the dataflow that you're looking at - debugging is methodical since it's straightforward to map an output to a function, check the logic there, and then methodically traverse its dependencies because they are declared. - you can wrap functions/inject things at run time easily
- AceJohnny2 4y agoOfftopic: I'm saddened to see YAML get a bad rap for effectively being shoehorned to fit a task that it's just bad at. In my experience, YAML is a great format for legibly declaring a dict/array structure, with added benefits over JSON like anchors/references (effectively pointers, which thus allow it to describe a graph), comments, and overloads (great for defaults!). But YAML has no facilities for conditionals, loops, or any logic. So these get tacked-on, ad-hoc, by systems that need them, and that pulls YAML towards Greenspun's Tenth Rule ("Any sufficiently complicated [system] contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp") I'm glad better languages like Dhall exist for the problem-space that YAML is just not designed for.
- smitty1e 4y agoMy grief is seeing YAML/JSON browbeaten past being static textual files, and into being interpreted files with nasty embedded functions (looking at YOU, CloudFormation). My latest project is gaffing all that off and using .xlsx to hold configuration, openpyxl to load the .xlsx, and then transforming the content into a target format (terraform) in the python. Let each piece in the system do what it's good at.
- chii 4y ago> using .xlsx to hold configuration what the?! I would imagine that .xlsx is even worse than a plain text file for holding configuration. You have to open it with a spreadsheet editor, and how would you diff a binary format when committing into source repository?
- smitty1e 4y agoGit does binaries. Excel is on the desktop, and ot has diffing tools. This is a work project, not something for regular GitHub release.
- Octabrain 4y ago> Let each piece in the system do what it's good at. Althought I strongly dislike the idea of introducing Excel in any equation, I wholehearthly agree with that quoted statement of yours. However, if I were you, I would use csv format. It can be easily read/edit from Excel if that's a strict requirement, and in that way, you can keep a grepable plain text versioned in the repository (the csv itself). The best of two worlds I guess. Also, from the top of my head, the Python standard library has a module for reading CSV, so less dependencies too.
- eduction 4y agoReminds me of this Rich Hickey quote: “So how do we make things easy? … There's a location aspect. Making something at hand, putting it in our toolkit, that's relatively simple. … Then there's the aspect of how do I make it familiar, right? I may not have ever seen this before. That's a learning exercise. I've got to go get a book, go take a tutorial, have somebody explain it to me. … Then we have this other part though, which is the mental capability part. And that's the part that's always hard to talk about, the mental capability part because, the fact is, we can learn more things. [But] we actually can't get much smarter. We're not going to move; we're not going to move our brain closer to the complexity. We have to make things near by simplifying them. But the truth here is not that there are these super, bright people who can do these amazing things and everybody else is stuck, because the juggling analogy is pretty close. Right? The average juggler can do three balls. The most amazing juggler in the world can do, like, 9 balls or 12 or something like that. They can't do 20 or 100. We're all very limited. Compared to the complexity we can create, we're all statistically at the same point in our ability to understand it, which is not very good. So we're going to have to bring things towards us. And because we can only juggle so many balls, you have to make a decision. How many of those balls do you want to be incidental complexity and how many do you want to be problem complexity?” https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/SimpleMadeEasy.md https://github.com/matthiasn/talk-transcripts/blob/master/Hi...
- rrauenza 4y agoNaming things to be easily searchable, especially in dynamic languages, is sadly very under valued by a lot of people.
- ggm 4y agoAnything in Python which uses ZIP() instantly hits my brain exploder, or one of those nested "do it for this array, iteratively, for this conditional" Anything using the ternary operation concept Anything using recursion Anything which has a self or implicit this in it, which is contextually undefined in the point of view, and has to be grokked as "the thing it should be, whatever it is" Anything which says "you aren't meant to understand this" The cognitive burden of being an (english?) speaker, with somebody who speaks in complex multi-clause sentences, with parenthetical statements but you don't know until the very last sentence WHAAT THE HELL IT IS they are on about. That guy. Thats generic functions in a function stack calling the one which says which of a million things this stack of calls is being applied to.
- zelphirkalt 4y agoThat is listing quite a lot of normal programming things. Of course powerful features need more thinking. I think you might discover in many cases these things are not a brain explode.
- ggm 4y agomany years in programming has not cleared these cognitive burdens. 44 and counting. I mean sure, I'd love to stop being astonished, but the truth is I'm not. I had this in card decks and uplifted into glass ttys over time. I have to re-read how to do lambdas more often than I care to try and remember. Every time I do, I ask myself why I'm doing it. If you are one of the cogniscenti who don't suffer this cognitive burden please treat the rest of us kindly. "oh, you mean you can't read music: how funny I can hear the entire orchestra"
- zelphirkalt 4y agoAt least about recursion I can say it only really clicked, after working through part of SICP and The Little Schemer. It is like avoiding to think about the potentially endlessly deep recursion, but thinking about the current level and what the meaning is. Sometimes however, there will be a recursion, which dumbfounds me as well :) I still feel I improve though. Just the other day I came up with a pair of mutual recursive functions, as if it was nothing, to solve a specific problem, by splitting it into 2 subproblems (or maybe 2 states in an automaton). Often there is a very clear idea behind a recursion, that, once one has heard it, becomes completely obvious. Maybe not always. About ZIP: Imagine you wanted to work on 2-tuples made out of pairs of elements from 2 lists. That's what ZIP does. Maybe also works for more than 2 lists, I don't know.
- pmarreck 4y agoCould a programmer with lower cognitive load capability paradoxically lead to code that has less complexity?
- Timpy 4y agoI think you would probably find a lot of naive programming and other amateur mistakes. Maybe there's a sweet spot where you want to be just smart enough to solve the problem in an elegant way but too lazy to abstract and overcomplicate things.
- geocar 4y agoI think it depends on what ideas the programmer has and puts to work in the task of telling the computer what to do. If the ideas are ideal, the program will be as small and fast as it can be, but if they are not then there will be an inefficiency. That is to say, if someone shows you code that is smaller and faster, then it has more-ideal ideas. Now few programs are built with ideal ideas[1] and people with "more capability" can use more simpler, less-ideal ideas to tell the computer what to do, but people with "low capability" must only use ideal ideas (or nearly-ideal). But how likely it is someone with a low cognitive load capability could have the ideal ideas? If you think of programming as a purely incremental thing, then this must seem impossible, but if you believe in evolution then you can probably understand sometimes "weird things happen" and if the weirdness is successful, then you'll get more weird things. It is for this reason I think the better programmer (more ideal ideas) probably has a lower cognitive load capability, but so does the worse programmer, so the important thing to focus on is a definition of "success", which on the long-scale will be different for the programmer than (say) the company they work for. Put another way: If you want a job, then making sure you can program like others is important, but if you want to retire young, then making sure your program makes you money and runs forever is probably more important. What would your employer prefer? [1]: If you aren't following what I mean by ideas here, Iverson calls them "tools of thought" and I can highly recommend reading: https://www.jsoftware.com/papers/tot.htm https://www.jsoftware.com/papers/tot.htm
- barking_biscuit 4y agoI think you need to define "lower cognitive load capability" first. There's a multitude of reasons why people can't handle cognitive load that all have different dynamics. The combination of traits I've seen lead to consistently less complex code is developers that are highly intelligent and hence more capable of building abstractions and who have a very low tolerance for frustration. The cognitive load of the spaghetti solutions they deal with grates on them a lot more than the average bear and since they are capable of seeing how to achieve the same task with less cognitive load they do it, so that they no longer have to deal with the frustration and can be comfortable.
- revskill 4y agoFor example, in JS apps, all of my function arguments include a `shouldThrowError` params (default is falsy), so we pass control to the call site instead of blindly throw error. That makes the whole composition more clean.
- chaosprint 4y agovery insightful article. I think I will read it several times. I think my project Glicol (https://github.com/chaosprint/glicol https://github.com/chaosprint/glicol) can also be an example. I try to use text-based style to represent synth connections and many musicians found it quite intuitive. I have been very addicted to OOP and I tried to design another language with FP paradigm, but finally I landed at this graph-oriented live coding language as I feel the declarative style has less cognition load naturally but I want to avoid the "problematic" aspect of FP.
- barking_biscuit 4y ago>If we can load only a limited number of “chunks” into working memory, how big can these chunks be? The answer is interesting: it seems that it does not matter I always try to work at reducing cognitive load and one of the principles I employ is reducing the individual number of chunks in the system as a whole. There are a myriad of ways to do this. One of the most pernicious things code can do is to make us ask questions of it because as soon as a piece of code leaves you wondering it has just loaded a chunk into your working memory hence removed some of the available capacity. What's worse is that chunk isn't valuable on its own. Instead it's a placeholder chunk that takes you from wondering to wandering as you deload all the chunks you had in working memory and start a process of navigating around the codebase to build up enough connections between the pieces to where you can collapse your new understanding down to a single chunk of insight. You then reload all the chunks you originally had and now that your placeholder chunk has been replaced by your newly acquired chunk of insight you can finally reason about the code you were trying to. This process sometimes takes seconds, sometimes minutes, sometimes hours, sometimes days, sometimes weeks, sometimes months. It's absurdly wasteful. Don't make me think! Opportunities to remove cognitive load are everywhere. You have a method that takes a parameter, what's the first thing a developer wonders about that parameter? Can it be null? If it can be null, how do these other lines of code behave with respect to that? If your programming language has an affordance that allows you to declare "the value of the parameter can't be null at this point" all of those questions drop away. System invariants are the same. You often see developers struggling with code that is trying to work out whether an invariant holds and what to do about it if it is violated at some point during the processing of something. The chunks of working memory used by those "but how do we handle X if Y is true at this point?" are cognitive load that you can completely nuke if you check the invariants hold right at the beginning and only do subsequent processing in the case that the invariants aren't violated. The conversation becomes "no need to worry about handling X here because if this code is running it means Y is definitely false". There's all kinds of things like different versions of the same framework, or competing frameworks with the same affordances. All of that stuff adds to cognitive load. A developer asks another developer "why do we use both xUnit and NUnit in our tests?". A half an hour conversation between 4 developers ensues. It's amazing the difference you can make by simply subtracting differences! Cognitive debt isn't the right metaphor, though the existing definition of it recounted in the article certainly reminds of the plight of an IC in the trenches. My term for this is "technical tax". A permanent % reduction in available capacity stemming from the cognitive load of the technical solutions. I'm always working to move the team and the org into a "lower technical tax bracket". Edit: also I don't necessarily agree that intrinsic cognitive load cannot be reduced. It's only true on a technicality. Yes, that cognitive load is indivisible from that domain and there is nothing you can do to change that. But that's not the point. It isn't the domain that experiences cognitive load, it's the developer working in the domain. What we have to manage is the cognitive load the developer is experiencing and making sure it's at an appropriate level. What you really need to ask of yourself and your developers is "what is the total amount of intrinsic cognitive load across all the domains and pieces of software you are responsible for and is that appropriate or too much for you?". An absolutely classic problem where I work is that teams own far too many things. There's just no way to be across all of it effectively.
- abrax3141 4y ago> I am not a psychologist, these are observations of a coder. I am a PhD cognitive psychologist and a coder with 50+ year’s, and I’ve worked directly on the topic you’re writing about. There’s a LOT to say about your interesting piece. Way too much actually. We may have to take it offline. But I want to nod to this: > In a parallel dimension ... computer hardware was based on SKI calculus. ... software has very few bugs, however, this universe has fewer programs, even fewer programmers, and the error messages suck. This is perhaps the funniest hacker joke I’ve ever heard! (Although, the Lisp error messages are actually pretty great. But I get the joke regardless.)
- pvillano 4y agogrug think hard to make simple code => grug think hard once grug write complex code to look smart => grug have to think hard every day forever
- rpeszek 4y agoHi, it is the author here. My coworker told me that my post is being discussed in Hacker News, I did not know! It will take me some time to digest what was said here. It looks like a lot of good discussion. Thank you!
- mikewarot 4y agoThere is another way to reduce cognitive load, and that is to build tools that allow the user to directly manipulate the abstract syntax tree, and treat the source as a product of the manipulation. Source code can be a view of the AST, and an output of this tool. DION was mentioned recently in a few threads, their demo[1] is quite impressive. [1] https://media.handmade-seattle.com/dion-systems/ https://media.handmade-seattle.com/dion-systems/ (watch the 1st video!)