Earlier quoted context omitted.
I was having this dilemma on my walk home. I try to write good idiomatic Django code, and know how to make it efficient in the ways described in Two Scoops (a book about Django best practices). I have inherited an app, parts of which are exactly the opposite of Django best practices (thin models fat controllers being the most obvious one - the application's documentation says that's the philosophy , while Django enco…
I think the best practice is to just refactor the bits that you need to touch. At a minimum avoid leaving them worse, and in an ideal world leave each piece you touch better for your having looked at it.
How to reduce the cognitive load of your code
221–230 of 239 posts
Re: How to reduce the cognitive load of your code
#222Earlier quoted context omitted.
The question is why you need a helper function? IMO, public functions are a special case and your generally better off using different naming schemes for internal and external functions. Granted, if it's pure pass-through then reusing the name is a non issue. Foo(x){foo(x);} is not confusing. Foo(x){junk; foo(x);} is. One option is Foo(x){validateForFoo; ValidedFoo(x);} Alternatively for private functions JunkFoo(x){…
The computation represented by "foo" could actually not be contributing any new semantics to "foo". It could just be some boiler plate that is needed to extract and isolate various resources out of context "x", so that these pieces can then be passed to the low-level "foo", which knows nothing of the aggregate "x". "junk" could be some locking an dunlocking, or debugging, or preparing the display in some way or whate…
SortGuiElement(){junk; SortUserNames(); junk;}
SortUserNames(){junk;}
vs. SortNames(){junk; sortNames() junk;}
sortNames(){junk;}
It might seem obvious and the code might be identical, but I see the second case very frequently in other peoples code.Re: How to reduce the cognitive load of your code
#223Earlier quoted context omitted.
Unit tests tell you what that small thing you did ages ago was meant to do, and what it does in different circumstances. If you have the discipline to thoroughly test your code(and the knowhow to not write brittle tests), it can really pay off.
>If you have the discipline to thoroughly test your code This isn't the issue. I, and I suspect many others, simply don't have time to thoroughly test code. It's the age-old issue of "Business doesn't rely on good code. It relies on delivering the product of that code." Up until the ship is both on fire and sinking - nobody cares about sailing a good ship. They'll settle for the shoddy lake boat and ride it out as lo…
Re: How to reduce the cognitive load of your code
#224Earlier quoted context omitted.
In my experience, most bad code is written by dogmatic cargo cult programmers that are more interested in writing code that adheres to their pet development philosophy or framework instead of programming to solve a problem in the simplest way possible.
Think we all got different experiences there. My main problems have been with people who insist on just churning out features in the most straightforward way without doing any kind of upfront thinking. You end up with reams of copy past coding, code duplication and so much code that it is very hard to keep track of what is going on. Like e.g. if you are parsing a file, and it is complicated you can save a lot of time…
Re: How to reduce the cognitive load of your code
#225Earlier quoted context omitted.
The computation represented by "foo" could actually not be contributing any new semantics to "foo". It could just be some boiler plate that is needed to extract and isolate various resources out of context "x", so that these pieces can then be passed to the low-level "foo", which knows nothing of the aggregate "x". "junk" could be some locking an dunlocking, or debugging, or preparing the display in some way or whate…
If your stripping boilerplate then your operating on different things. Which seems more readable? SortGuiElement(){junk; SortUserNames(); junk;} SortUserNames(){junk;} vs. SortNames(){junk; sortNames() junk;} sortNames(){junk;} It might seem obvious and the code might be identical, but I see the second case very frequently in other peoples code.
You want:
SortNames(){junk; SortNamesImpl(); junk;}
sortNames(){junk;}
or whatever: SortNamesGuts(), InternalSortNames(), DoSortNames(), LowLevelSortNames(). Anything but just flipping the case of a letter or two in the "SortNames" identifier.Re: How to reduce the cognitive load of your code
#226Earlier quoted context omitted.
> Now I belive that most bad code out thare is made by overworked and tired programmers in a rush to deliver something that works. I would agree. But I think putting up with those conditions is a different sort of laziness, and agreeing to produce garbage is a different sort of incompetence. Looking back on the times I've done that myself, I deeply regret it. Programmers have a lot more power to shape process than th…
While we do have a good amount of power, they still have the ultimate power in that they write the checks.
And a given check only has power over you to the extent that you let it. Most programmers will have little trouble finding a job if they have good professional networks or are otherwise willing to work at having options. If you are confident that a just-as-good job is easily available, you can be much braver in the one you have.
Re: How to reduce the cognitive load of your code
#227Earlier quoted context omitted.
Except if you do if(foo = null){} it won't compile in java which is exactly what you want to happen. So using it in java is just cognitive load and provides 0 benefits.
Habits are hard to break. Switching back and forth between habits leads to mistakes. There's a trade-off here. I'm not going to say one is definitely worth it vs. the other, but if we pretend the disadvantages of one option don't exist, we lose the ability to make appropriate judgements.
Re: How to reduce the cognitive load of your code
#228Earlier quoted context omitted.
If your stripping boilerplate then your operating on different things. Which seems more readable? SortGuiElement(){junk; SortUserNames(); junk;} SortUserNames(){junk;} vs. SortNames(){junk; sortNames() junk;} sortNames(){junk;} It might seem obvious and the code might be identical, but I see the second case very frequently in other peoples code.
Re-using an identifier with just a case difference is criminal. You want: SortNames(){junk; SortNamesImpl(); junk;} sortNames(){junk;} or whatever: SortNamesGuts(), InternalSortNames(), DoSortNames(), LowLevelSortNames(). Anything but just flipping the case of a letter or two in the "SortNames" identifier.
Amway IMO, SortNames() and Internal/Do/LowLevel/SortNames() are almost as bad because just looking at the names it's not obvious what's going on. Yes, visually they look different which helps and consistency can make things even more readable. But, even just SortNamesHappyPath() gives some idea of what's going on.
Re: How to reduce the cognitive load of your code
#229Earlier quoted context omitted.
I don't think the Haskell typing system is powerful enough for completely replacing prefix labels. Marking something unsafe is a best case scenario. Separating lines from rows would require a huge amount of boiterplate to preserve the numeric operations, and one still can not create a library that will check something like: let l = 5 :: Meter w = 4 :: Newton in l * w :: Joule
Representing constraints in the type system is always an engineering tradeoff---how much type level machinery do you want to build vs the effort required to build that? Not sure what you mean by separating lines from rows. In the example you give of computing with units, I've seen examples of such systems in Scala (e.g. http://www.squants.com/ ) and F# comes with something built-in for this (IIUC). You might be inter…
It's the example Joe Spolsky used on the blog post about prefixes that everybody keeps pointing to. He showed code that worked on rows and columns (not lines, sorry) on a table, using prefixes to avoid mixing them.
Haskell types do support this use, but you'll have to declare both types as Integral and Numeric, with the resulting boiterplate. I'm not sure exactly how to solve this, maybe a way to "lift" typeclasses out of a newtype declaration would be general enough. It is probably possible to do with template Haskell, but that is already outside of the language.
That Scala library is interesting, although it looks like lots of the work is done at run time. Also, it looks like Haskell is able to do it [1]. (It's a recurring theme of mine, to complain that something can not be done on Haskell, just to discover somebody that did it.)
Re: How to reduce the cognitive load of your code
#230Like often with this kind of article it barely scratches the surface. "null != variable" will confuse people is downright silly. People confused by this won't have an inkling of what any non-hello-world program does. The rest has some validity, but it focuses on syntax and programming in the very small. It might take a bit of effort, but I can make sense of a tangled function (that's not an excuse to code sloppily th…
I agree that big, deep stuff like architecture and abstractions can be daunting, but I wouldn't be quick to dismiss style and formatting as mere nitpicks. Code clutter can have an outsize effect downwind of those who create it. A codebase is like a home. We all have to live in it. Architecture and abstractions are like the furniture and appliances. Code formatting and syntax are the nicknacks, paper bills, decoration…