29 ms·
Simple Ways of Reducing the Cognitive Load in Code
- vinceguidry 10y agoI started doing this a year ago and it really helped me to maintain code. My new goal is to be able to read other's code, make it more readable, and fix the problem just as fast as it would have been without slight, constant refactoring. I want to run a team so I can teach the whole team to work this way. Then I'll handle all the complex refactorings, which I really enjoy doing, while they greenfield new features. If they can write code this way, then I'll be able to refactor it without having to study it to figure out what it's doing.
- taspeotis 10y agohttps://news.ycombinator.com/item?id=11380762 https://news.ycombinator.com/item?id=11380762 How to reduce the cognitive load of your code (chrismm.com) 304 points by ingve 90 days ago | 232 comments
- s_dev 10y agoPeople sometimes ask why it's necessary to point out reposts. I think it's helpful because you get an extended and often alternate commentary and can make for interesting reading and comparisons.
- escherize 10y agoI'd like to add one: let your tools do the work for you. It may seem like a pain to learn the tooling behind what you do, but once you internalize it, it becomes a superpower. An example is that I use Clojure Refactor Mode (with CIDER) for emacs. A trick (and treat) that a lot of Clojure code uses is the arrow macros: -> and ->>. Clojure Refactor Mode has thread-first, thread-first-all, thread-last, thread-last-all and unwind. Since I've committed those to my long term memory, I can just call thread-first-all on something like: (reduce * (repeat 4 (count (str (* 100 2))))) and get: (->> 2 (* 100) str count (repeat 4) (reduce *)) This is so huge, because many times changing the levels of threading makes reasoning about the code so much easier.
- junke 10y agoI agree with the tooling part. I tend to prefer the functional version to threading because (1) honestly, like fluent interfaces, it seems overused (2) function application is damn easy to read and (3) as soon as you have as many nested operations, it can and should be refactored into meaningful auxiliary functions. The first line reads as: Multiply all ... 4 copies of ... the length of ... the string "200". So, basically, the length of that string multiplied by itself 4 times? (exponent). The other form is more like step-by-step instructions, which is nice. However results are implicitly being passed at the first or last argument (I don't always remember which), and most everyday functions don't fit in the first/last category.
- loganmhb 10y agoOne of the nice things about the Clojure standard library is that most everyday functions actually do fit the first/last category (by design). Functions operating on sequences (map, filter, reduce, etc) take the sequence as the last argument and are suited for use with the ->> macro, while functions operating on data structures in a non-sequence context typically take the data structure first (assoc, conj, update) and are good for ->. So you get either: (->> (range 10) (map inc) (filter even?) (take 2)) ;=> '(2 4) or (-> {:body {:some {:json :data}}} (assoc-in [:body :some :more-json] :more-data) (assoc :status 200) (update :body json/generate-string)) ;;=> {:body "{\"some\":{\"json\":\"data\",\"more-json\":\"more-data\"}}", :status 200} It doesn't work all the time, obviously, and it can be easy to get carried away with 15 threaded map/filter/reduce calls that should be factored into separate functions, but most of the time I find it to be a nice idiom that substantially improves readability.
- rakpol 10y agoThat's like the function composition operator [1] in Haskell, right? Very neat :D I wonder if there's an equivalent macro in Scala ... [1]: http://lambda.jstolarek.com/2012/03/function-composition-and-dollar-operator-in-haskell/ http://lambda.jstolarek.com/2012/03/function-composition-and...
- 10y ago
- majewsky 10y agoI really like the advice from "Perl Best Practices" to code in paragraphs. Sometimes, a large function cannot be broken up usefully, because a lot of state needs to be shared between the different parts, or because the parts don't have a meaning outside of the very specific algorithm. In that case, code in paragraphs: Split the function body into multiple steps, put a blank line between these and, most importantly, add a comment at the start of the paragraph that summarizes its purpose. Now when someone else finds your function, they can just gloss over the paragraph headings to get an idea of the function's overall structure, then drill down into the parts that are relevant for them.
- a3n 10y agoThis is one of my favorite things.
- tigershark 10y agoI completely disagree, every method can be split in private methods. In that way you don't need awful and unhelpful comments in the middle because you can understand what it does simply from the method name.
- criddell 10y ago> you can understand what it does simply from the method name That can be tough sometimes. How do you handle the case where you've created a function just to package some block of code that would otherwise be repeated 40 times? You end up with function names like add_to_list_when_cromulent() or even worse rebuild_stats_helper() Or you have the situation where every time you do action A, it usually needs to be followed with action B. Because you want functions to do one thing only you have two functions action_A() and action_B(). But since you are always going to do them in pairs, you end up with a group action_A_and_B() that just calls the two functions sequentially. I think I've settled on helper functions that are static or in anonymous namespaces (I work in C++) whenever possible.
- coredog64 10y ago
- iamleppert 10y ago"Use names to convey purpose. Don't take advantage of language features to look cool." I can't say enough about this. Please write code that is easy to read and understand, not the most compact code, and not the most "decorated" code, or "pretty" code or neat because it uses that giant list expression or ridiculous map statement thats an entire paragraph long. Similarly what bugs me is when I receive a pull request where someone has rewritten a bunch of code to take advantage of new language features just for the hell of it and that did not lead to an increase in clarity. I guess its in vogue now to add a lot of bloat and complexity and tooling to our code. "Use the simplest possible thing that works." Tell that to the Babel authors with their 40k files...
- a3n 10y agoThis isn't new, it has always been thus.
- sevensor 10y agoIndeed, and every piece of advice about coding style is sometimes wrong.
- delecti 10y agoI recently got a code review that in several places suggested I switch to the new Java 8 stream API [1]. I just flatly responded that it was far less readable, even if I could condense a half-dozen lines of code down to one. Where I can quickly scan over a foreach loop to get the jist of what it's doing, I have to closely examine each call in the new approach to have any idea what it's doing. [1] http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html http://www.oracle.com/technetwork/articles/java/ma14-java-se...
- eru 10y agoAs long as the one line is less than six times harder to read than any one of the previous lines, changing to the new approach seems like a win?
- 10y ago
- TickleSteve 10y ago...and another: Use of whitespace (vertical and horizontal) to group and associate code with related parts. Its a trick borrowed from graphic design, but negative-space works really nicely.
- criddell 10y agoI've come to appreciate this as well and it's what has driven me to prefer spaces over tabs.
- phaed 10y agoSounds like you need to split your methods/files into smaller single-purpose chunks.
- TickleSteve 10y agono... nothing to do with that... This is about visually grouping related things together, not decomposition of functions.
- userbinator 10y agoOn the other hand, maybe increasing the cognitive load is beneficial to everyone in the long term: http://www.linusakesson.net/programming/kernighans-lever/ http://www.linusakesson.net/programming/kernighans-lever/
- jboy 10y agoThis article is a good start, but I found it much too light on detail. Each section ended just when I was ready for it to dive into details! For example, in the final section "Make it easy to digest": > Using prefixes in names is a great way to add meaning to them. It’s a practice that used to be popular, and I think misuse is the reason it hasn’t kept up. Prefix systems like hungarian notation were initially meant to add meaning, but with time they ended up being used in less contextual ways, such as just to add type information. OK, great, I agree -- but what are some suggestions/examples of good prefixes? What are some examples of bad prefixes that we should avoid? To illustrate the sort of detail I'd like to read, here is an example of my own of good/bad method names that would be greatly improved by judicious use of prefixes. My standard go-to example for ambiguous naming is the std::vector in the C++ STL. There is a member function `vec.empty()`: Does this function empty the vector [Y/N]? Answer: No, it doesn't. To do that, you instead use the member function `vec.clear()`. There is no logic a priori to know the difference between `empty` & `clear`, nor what operation either performs if you see it in isolation. You must simply memorize the meanings, or consult the docs every time. In the C++ style guides I've written, I've always encouraged the prefixing of member function names with a verb. Boolean accessors should be prefixed with `is-`. The only exception should be non-boolean accessors such as `size` (which has its own problems as a name). Forcing non-boolean accessors to be preceded by a verb invariably results in names like `getSize()`, where `get-` adds no useful information, clashes with the standard C++ naming style for accessors, and really just clutters the code with visual noise. Using these prefixes: (depending upon your project's preference for underscores or CamelCase) .empty -> .isEmpty() or .is_empty() .clear -> .makeEmpty() or .make_empty() As an additional benefit, the use of disambiguating prefixes also enables the interface designer to standardize upon a single term "empty" to describe the state of containing no elements in the vector, rather than playing the synonym game ("empty", "clear", etc.). The programmer should not need to wonder whether "clear" empties a vector in a different way.
- honkhonkpants 10y agois_emtpy and make_empty are just going to irritate every C++ programmer in the business, since all the STL containers use empty and clear.
- robert_tweed 10y agoThis is a nice post on the subject of readability, though I mostly like that the title does not use the often misused word "readability" at all. I now prefer to talk about understandability instead, which usually boils down to cognitive load. This is one of the things that Go has got very right in its design, though it is often badly misunderstood. Advocates of languages like Ruby often refer to the "beauty" of the code while ignoring the fact that many of the techniques employed to achieve that obscure the meaning of the code. The main problem I have with the term "readability" is that it encourages writing of code that reads like English, even if it obscures the details of what the code does. In the worst cases, the same set of statements can do different things in different contexts but that context may not be at all obvious to the reader. One of the first books I read when I was learning C years ago talked about avoiding "cutesy code". That was particularly in reference to macro abuse, but it's always stuck with me as a good general principle. It applies equally to excessive overloading via inheritance and many other things that make it hard to tell what a given statement actually does, without digging around in sources outside of the fragment of code you are reading. In many ways the art of good programming is, aside from choosing good names for things, maintaining the proper balance between KISS and DRY.
- BigJono 10y agoI've been dwelling on this idea of readability vs comprehensibility for quite a while now, working on front-end projects in Javascript. Everyone seems to be using the airbnb style guide for their projects now, and whenever I look through these projects I can't help but feel that people are committing some cardinal sins that should be blatantly obvious to most developers. There's such a push to make everything "simpler" and "neater", that people are willing to trade any amount of comprehensibility to make their code look nicer. A key example: Since object destructuring became a thing, I often see logical objects being destructured for the sake of saving a few keystrokes. Ditto for framework constructs such as React's component props. Yes it's "ugly" to see "this.props" scattered around the place, but it makes it crystal clear what data is coming from where. If you destructure everything into it's own variable then how do you distinguish between function arguments, closured variables, object properties, React props etc. And the worst thing about this practice is that it almost invariably happens in functions that are large and complex enough to "need" it, which is where it does the most damage. I also think there's a case to be made for avoiding function declaration syntax inside objects, and ES6 class syntax in general. They seem to exist only to try and flatten a learning curve that's not that bad in the first place. Javascript doesn't have classes, it has objects and prototypes, and you're not declaring a function on a class, you're declaring a property on an object, which happens to be a function. Why are we so quick to introduce ambiguity just to abstract away from minor complexities? Sure this code is "easier to read", but it's a lot harder to comprehend the specifics of what it's doing. And in any non-trivial project there is going to be a time when it's the specifics that matter.
- cauterized 10y agoI happen to find the principle of single level of abstraction does more to reduce cognitive load than all these tips put together.
- valine 10y agoAs a junior dev I can confirm the advice about junior devs is very accurate. An anecdote: I recently started working with a team on their half completed web app. They had so many dependencies, and tools for managing dependencies, it took me far longer than it should have to become productive. It's obviously not my place to question which technologies they use, but it can be frustrating.
- maxaf 10y agoIt is your place to question everything. Your contribution to the team, even if it comes in the form of perspective alone, is valuable anyway.
- edejong 10y agoI'd go even further and say that newcomers to teams are often the most able to pinpoint essential flaws in the development process.
- deepaksurti 10y agoAnd that applies irrespective of a newcomer is junior or senior. There is hardly a substitute for a fresh pair of eyes t to reveal what one thinks is cool design, code et al is not so cool after all.
- JohnL4 10y agoWe need to distinguish between "I don't understand this and I'm not going to bother to try before I start criticizing" and "Ok, I understand why you did this, but have you considered this alternate approach?" (and maybe "I don't understand this, and I think we need better docs here.", but that's already been covered). (Some) new devs seem to classify themselves into "I'm just a clueless noob" and "I'm the new hotness".
- rimantas 10y agoExcept often the things pinpointed are not flaws just different from that they are used to.
- fchopin 10y agoFor the most part, I agree with this. The biggest problems I've had at work have been due to constructs that were a neat idea but just add to the complexity of figuring out the application. Throw in a bunch of business-specific engineering terminology that is not defined anywhere for the development team, and it becomes a wicked PITA to learn. However, the one-liner example and the chained English-sounding methods, I think might be taken the wrong way. Both can be done well.
- hoorayimhelping 10y ago>Junior devs can’t handle overuse of new tech. heh, I'm a senior dev and I have trouble with the overuse of new tech. It's hard for me to learn when there are too many variables in play; early on, it's hard to know which bit is doing what.
- ninjakeyboard 10y agoMy biggest pet peeve is when people use pattern names in class names. You don't need to call things strategies if you're composing in behavior. Just call it the behavior. val weapon = Sword() weapon.attack(up) weapon = Bow() weapon.attack(left) Often the pattern's implementation drifts a bit from the by-the-book implementation and it ends up being something ALMOST like the pattern but it's not quite anymore. Or it's more. Then the pattern name is still stuck there and it causes more confusion than it helps to clarify.
- qaq 10y ago"Using MVC? Place models, views and controllers in their own folders" This works on smaller projects on large projects it's often easier to group things by component
- markbnj 10y agoGood advice and worth reading especially for younger devs. With respect to... >> Prefix systems like hungarian notation were initially meant to add meaning, but with time they ended up being used in less contextual ways, such as just to add type information. Hungarian notation was pretty cumbersome to read, actually, and I think the main reason it fell out of use is that editors and IDEs began to make type and declaration information available for symbols in a consistent way, so it was no longer much of an advantage (and perhaps a disadvantage) to use a manual convention that was usually applied inconsistently.
- rakpol 10y agoFrom the perspective of a younger dev, this seems like excellent reading for older devs, who tend to enforce their personal style without deferring to the de facto language standards (or PEP 8 for those working in Python). In fact, perhaps everyone could do with downing a half dozen humble pills and optimize their code for harmonious human interoperability than anything to do with machines :)
- jahewson 10y agoOne of the major functions of Hungarian notion was to communicate information which was not contained in the types of the actual variables, for example an int could be a count of bytes 'cb', or perhaps a handle 'h', etc. But it ended up being mostly misused to communicate redundant type information, such as a char* being 'sz' (zero-terminated string), which tells us nothing we didn't already know. As you say, better IDEs made the latter kind of naming no longer advantageous (if it ever was) but that was true for some time before Hungarian notation fell out of favour - the real reason being a rejection of its redundancy within MS during the transition to .NET. Joel Spolsky details the good and bad of Hungarian notation here: http://www.joelonsoftware.com/articles/Wrong.html http://www.joelonsoftware.com/articles/Wrong.html
- slededit 10y ago'sz' is pretty useful if you have pascal strings floating around.
- donatj 10y agoFluent interfaces make code a joy to write and a huge burden to later review and reason about, particularly when the object you are interacting with changes mid way through on certain calls. They are something I loved when I was younger, but now doing code reviews they are the bane of my existence.
- indubitably 10y agoKeep your personal quirks out of it Don’t personalize your work in ways that would require explanations. I like taking advantage of variables to compartmentalize logic.
- mattmanser 10y agoNot the same thing. Randomly I'm working on some fairly awful code today that has the one redeeming feature that it divided and conquered as described in the article. It made it fairly trivial to find the exact spot the problem was happening. At no point reading the code did I think that assigning key values into variables along the way that were named to describe exactly what they represented and then all added up at the end was a personal quirk of the code. That's a world of difference compared to using the fairly odd: if(null != thing)
- dreamsofdragons 10y agoThis article is a mix of good advice, terrible advice, and conflicting advice. Statements like "Avoid using language extensions and libraries that do not play well with your IDE." are foolish. Pick your language primarily on the best fit of the language for the problem space, second, pick a language that you're comfortable with and knowledgeable about. Picking the wrong tool simply because it works well with another tool, is horrible advice.
- jorgeleo 10y ago"How can a new developer just memorize all that stuff? “Code Complete“, the greatest exponent in this matter, is 960 pages long!" First... do not memorize, but internalize, understand why they work, and when to apply which one. Use them to solve the problem of your code been read in 6 month by a serial killer that know your address. Second... 960 pages. If you really want to advance the craft, if you really want to become a better developer, then you don't measure by the number of pages (<sarcasm>what a sacrifice, I have to read</sarcasm>), you measure by the amount of gold advice on the book. 960 pages is a lot of gold. Third... If you read the whole blog and understood the value in following the Cliff notes to the Cliff notes that this post is, then you should be looking forward to read the 960 pages.
- phaed 10y agoWas about to come here to say this. This stuff was all written down decades ago.
- pyre 10y ago> Second... 960 pages. If you really want to advance the craft, if you really want to become a better developer, then you don't measure by the number of pages (<sarcasm>what a sacrifice, I have to read</sarcasm>), you measure by the amount of gold advice on the book. 960 pages is a lot of gold. I think that comment on the page length was just on the volume of stuff that one would have to memorize if they were to memorize (rather than internalize) the knowledge.
- TeMPOraL 10y ago960 pages is a light reading IMO :). One can hardly find a better time investment than reading a good book on a useful subject. Especially today, when quite often you can easily get access to the best knowledge mankind has on a topic. Books are awesome!
- joe_the_user 10y agoAs books go, Code Complete isn't intended to be memorized but to be understood. I would imagine a coder already having an internal model of how to write code and using a book like Code Complete tweak and improve that model. Also, I read something like Code Complete for the same reason I've read the parent blog. Even though I feel like I know the basic points here, writing good code inevitably is a trade-off and so one more idea of how to make the trade-off is useful.
- andy_ppp 10y agoOr rather more simply - do code reviews and decide on which of these things you want to include and teach everyone about: a) the agreed way b) other code they haven't worked on in the process. Finally if you know someone else will be reviewing your code you'll produce better code in the first place.
- ViktorasM 10y agoStopped reading at "Place models, views and controllers in their own folders". No worse way to organize your code than classify by behavior type. "Here are all the daos", "here is all business logic", "here are all the controllers". You add a feature as small as resource CRUD and scatter it's pieces across the whole code base. No.
- greenshackle 10y agoThe guidelines for a framework I use is to put views and models in separate folders. Which means code for any model is spread out between at least two folders. Finding code is annoying.
- amirouche 10y agoTo avoid that Django does split by "app" or feature first.
- 725686 10y agoAgree. A few years ago I read this http://olivergierke.de/2013/01/whoops-where-did-my-architecture-go/ http://olivergierke.de/2013/01/whoops-where-did-my-architect... post which made a lot of sense to me. Also this: http://www.slideshare.net/olivergierke/whoops-where-did-my-architecture-go-11678054 http://www.slideshare.net/olivergierke/whoops-where-did-my-a...
- loco5niner 10y agoHonest question from someone with little real world experience outside .Net: This is MVC's convention, to "Place models, views and controllers in their own folders", and it's what I'm used to working with. Can you point me to resources outlining other methods (responding with google "XYZ" would be fine too).
- prawks 10y agoDjango's recommended project structure is one that immediately comes to mind. A project is broken down into "applications" each which have their own models, views, and controllers (among other things like forms, tests, etc.). Each "application" is an area of responsibility within the project, like payment or user management. As it's python, the 'views' module could technically be a folder with multiple files inside it, but they would all be grouped under their respective app.
- dingleberry 10y agoIf you don't have to name things, you have zero chance of getting bug caused by naming things That's why i love anonymous function. it frees me from names overload
- Waterluvian 10y ago"clever code isn't." Is what I try to teach all who will listen. Good code should never be illegible to newbies. And if they can read your code, they can learn way faster.
- tmaly 10y agoI own Code Complete, but I felt I got better value out of the Clean Code book combined with the Pragmatic Programmer. I did find some value in Code Complete, but it is a little too long for my tastes. The naming and abstract data structure sections were probably my favorite parts of that book.
- alfiedotwtf 10y agoIf you're just starting out in your career, reading Code Complete is like gaining experience by osmosis. Then once you know what you're doing, Pragmatic Programmer is like a light refresher that you read once every few years.
- bdavisx 10y agoYes, I read the first edition many years ago - it was a huge benefit to my naive "bash the code out however I can" practices. Now, when reading it, I'm kind of like "yes, that's good, except when..." So you learn to temper the rules with experience. But in the beginning of your software development journey, you need something to keep you in line.
- drtz 10y agoAll code does not need to be easily understandable by a novice developer. Minimizing cognitive load is certainly a good thing, but using overly simple grammar for a complex task leads to unneeded verbosity. When writing software, as with any form of writing, you should keep your audience in mind as you write.
- reikonomusha 10y agoI've noticed recently that especially in online discussions, the term "cognitive load" is used as a catch-all excuse to rag on code that someone doesn't like. It appears to be a thought-terminating cliché. There's definitely room to talk about objective metrics for code simplicity, which are ultimately what many of these "cognitive load" arguments are about. But cognitive load seems to misrepresent the problem; I think it's hard to prove/justify/qualify without some scientific evidence over a large population sample. With that said, the article presented fine tips, but they seem to be stock software engineering tips for readable code.
- SonicSoul 10y agoIn cognitive psychology, cognitive load refers to the total amount of mental effort being used in the working memory seems like a correct usage to me. Anytime an ATM displays weird confirmation buttons like "Sure" instead of "Yes" or bloated confirmation text instead of "transaction completed" this increases cognitive load. I agree that it is debatable what kind of code exactly causes the least strain, but at least the term doesn't seem to be especially scientific.
- reikonomusha 10y agoIt's not incorrect necessarily, just unqualified. Cognitive load is hard to meaningfully substantiate; it is person and experience dependent.
- deleted 10y ago[deleted]
- CuriousSkeptic 10y agoActually, not at all. It's directly measurable http://www.ncbi.nlm.nih.gov/pubmed/17833905 http://www.ncbi.nlm.nih.gov/pubmed/17833905 "The pupil response not only indicates mental activity in itself but shows that mental activity is closely correlated with problem difficulty, and that the size of the pupil increases with the difficulty of the problem"
- thaw13579 10y agoThese seem like good rules to follow, but there's nothing to suggest that they reduce cognitive load. To make that claim, you need experiments testing brain function or at least people's behavior...
- thaw13579 10y agoTo follow up with a point of comparison, this is the kind of work that can make a claim about how cognition and coding are related: http://www.cs.cmu.edu/%7Eckaestne/pdf/icse14_fmri.pdf http://www.cs.cmu.edu/%7Eckaestne/pdf/icse14_fmri.pdf
- collyw 10y agoGet a decent high level architecture, good, consistent database design and you don't write anywhere near as much application code. Start hacking about using one field for two purposes or having "special cases" and everything starts to get messy. These special one off cases will involve adding in more code at the application level increasing overall complexity. Repeat enough times and you will code a big ball of mud. Instead people argue about number of characters per line or prefixing variable names with something and other such trivialities. (These things do help readability, but overall I think they are quite minor in comparison to the database design / overall architecture - assuming you are writing a database backed application).
- reikonomusha 10y agoThere's relevance in talking about both micro- and macroscopic guidelines. Both are important. Very rarely does someone "read" an entire code base "with one look" and be able to deduce issues. You do, at some point, have to get into the weeds. Managing that experience is what articles like these are about.
- collyw 10y agoYes, there is value in both, but I only ever see people talking about the former.
- amirouche 10y agoThere are more people talking about code that don't know actual code than people that know what they talk about when they say code source. A software is not only a source code, it's many things: business rules, GUI, database, network, programming language etc. It's seems logical that there's more talking that is macroscopic from the point of view of coder's own microscopic. Hopefully, hackernews is here to help ;)
- fauigerzigerk 10y ago>Start hacking about using one field for two purposes or having "special cases" and everything starts to get messy. That advice is not as easy to put into practice as you make it sound. For instance, using one field for two purposes is often done to avoid special cases. I think the eternal problem of software development is that both being more abstract and being more specific comes with a cost, and the middle ground is always shifting as requirements keep changing.
- jonhohle 10y agoHis second example to "modularize" a branch condition is not functionally equivalent in _most_ in-use programming languages: valid_user = loggedIn() && hasRole(ROLE_ADMIN) valid_data = data != null && validate(data) if (valid_user && valid_data) … Is not equivalent to: if (loggedIn() && hasRole(ROLE_ADMIN) && data != null && validate(data)) … His version will always execute `validate(…)` if `data` is not null regardless of whether the user is logged in or has the appropriate role. Not knowing the cost of `validate(…)`, this could be an expensive operation that could be avoided with short-circuiting. It also seems somewhat silly (and I know it's just a contrived example), that a validation function would not also perform the `null` check and leave that up to the caller.
- saboot 10y agoPerhaps an alternative would be valid_user = loggedIn() && hasRole(ROLE_ADMIN) if (valid_user) { valid_data = data != null && validate(data) if (valid_data) { ... } }
- CGamesPlay 10y agoFor whatever reason, I'd prefer comments to this version. Note: I actually agree with the OP about pulling the logic into named conditionals whenever possible, but in the case you do want the short-circuiting behavior I would not bother with the variables at that point. if (loggedIn() && hasRole(ROLE_ADMIN)) { // User has permission to do this if (data != null && validate(data)) { // Submitted data is valid ... } }
- beernutz 10y agoI think part of the reason for doing it the way they do in the article is to reduce nesting. I saw the problem with missing the short circuit as well though which is why I like the suggestion of using if (isValidUser() && isValidData(data)) And checking for data being null in the isValidData method. There is a little overhead in the call and return if data is null, but the clarity provided seems like a win in these kinds of cases.
- 0xdeadbeefbabe 10y agoI believe maintainable style is less important than knowing how the thing behaves.
- kuharich 10y agoPrevious discussion: https://news.ycombinator.com/item?id=11380762 https://news.ycombinator.com/item?id=11380762
- Roboprog 10y agoThis article does a good job of encapsulating the prevailing Java "ignorance is strength" (worse/longer is better; abstraction is bad) paradigm. When are the right-tailers (in the bell curve) ever going to let you use new features to make your code shorter? Why learn complex concepts like "multiplication", when "tally marks" will do? I'm afraid I'm with Steve Yegge on this one, in regards to dislike of the "tools to move mountains of dirt" aspect. http://steve-yegge.blogspot.com.au/2007/12/codes-worst-enemy.html http://steve-yegge.blogspot.com.au/2007/12/codes-worst-enemy...
- unabst 10y agoMaximize order. Order is the lubricant for information. And if you back your reasons with guiding principles (aka philosophy) the specifics will remain obvious as well as sort themselves. These are the only ways to reduce cognitive load and they apply to any situation where one needs to understand something. After all, code is about understanding. Anecdotally, the specific methods mentioned in the article that seem most valid stem from the guiding principle of maximizing order, which drastically reduces the cognitive load of the contents of the article.
- athenot 10y agoAlong the same lines, use the right language for the abstraction you are dealing with. In a server environment, I prefer to have modular services linked together with some message queue. In web projects, this is what has kept me coming back to CoffeeScript: we found it less distracting visually, given the kind of code we were writing (heavy call-back oriented, lots of chained methods).
- stuaxo 10y agoHave to disagree on not placing null first in comparisons, it's a good way to avoid bugs.
- lenzai 10y ago""" Storing the result of long conditionals into a variable or two is a great way to modularize without the overhead of a function call.""" Ridiculous ! Not only caring about overhead is misleading, but introducing local variables is against refactoring principles.
- batguano 10y agoI'm surprised no one has cited this: http://xkcd.com/1695/ http://xkcd.com/1695/
- deleted 10y ago[deleted]
- deleted 10y ago[deleted]
- deleted 10y ago[deleted]
- randomacct44 10y agoMy current pet-peeve: - If your code deals with values where the units of measure are especially important and where they may change for the same type of value in different contexts, PUT THE UNITS USED IN THE VARIABLE NAME! I work primarily with systems that talk money values to other systems, some of which need values in decimal dollars (10.00 is $10.00) and some that need values in integer cents (1000 is $10.00). Throughout our codebase this is often referred to helpfully as 'Amount', unfortunately :( So much easier when you can just look at the variable.... 'AmountCents' -- this naming convention alone would prevent some bugs I've had to fix. Which points to something deeper that I've come to realize. Your code speaks to you, in the sense that when you come back to your own code 6 months later, there's a certain amount of "I don't know what this is doing" that you can chalk up to just not having looked at it for 6 months, but there is also an amount where you have to say "no, actually I didn't write this code clearly at the time". When evaluating my own progress that's a big metric I use - on average, how am I understanding my own code later? What I try and watch out for in myself is when I find myself not making something explicit in the code because of domain knowledge that I have. The 'Amount' example is a good one of this. The domain knowledge is that I know this particular system wants values in decimal dollars -- I mean it's totally OBVIOUS isn't it? Why would I bother writing 'Cents' at the end for something so obvious? Yet, even referencing domain knowledge is a higher cognitive load than just reading 'Cents' in the variable name. Not to mention the next engineer that comes along -- it's likely they won't have that bit of 'obvious' domain knowledge. I would vote both 'Code Complete' and 'Clean Code' as two must-read books for any programmer.
- hesselink 10y agoOr put the units in the type system: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/units-of-measure-%5Bfsharp%5D https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual...