The best codebase I have ever seen and collaborated on was also boring as fuck.
- Small, immutable modules.
- Every new features was coded by extension (the ‘o’ in S.O.L.I.D)
- All dependencies were resolved by injection.
- All the application life cycle was managed by configurable scopes.
- There was absolutely no boiler plate except for the initial injectors.
- All of the tests were brain-dead and took very minimal effort to write. Tests served both as documentation and specification for modules.
- “Refactoring” was as simple as changing a constructor or a configuration file.
- All the input/output of the modules were configurable streams.
There is more to it, but basically, it was a very strict codebase, and it used a lot of opinionated libraries. Not an easy codebase to understand if you’re a newbie, but it was absolutely brain dead to maintain and extend on.
Coding actually took very little time of our day, most of it consisted of researching the best tech or what to add next. I think the codebase was objectively strictly better than all other similar software I’ve seen and worked on. We joked A LOT when it came time to change something in the app pretending it would take weeks and many 8 pointers, then we’d casually make the change while joking about it.
It might sound mythical and bullshity, and it wasn’t perfect, it should be said that dependency injection often come in the form of highly opinionated frameworks, but it really felt like what software development should be. It really felt like engineering, boring and predictable, every PO dreams.
That being said, I given up trying to convince people that having life-cycle logic are over the place and fetching dependencies left and right always lead to chaos. Unfortunately I cannot really tell you guys what the software was about because I am not allowed to, but there was a lot of moving parts (hence why we decided to go with this approach). I will also reiterate that it was boring as fuck. If anything, my hot take would be that most programmers are subconsciously lying to themselves, and prefer to code whatever it is they like, instead of what the codebase need, and using whatever tool they like, instead of the tools the project and the team need. Programming like and engineer is not “fun”, programming like a cowboy and ignoring the tests is a whole lot of fun.
This! Software engineering suggests a certain professionalism wich unfortunately is hard to find. From an accessibility point of view I am simply not able to participate in these cowboy style events for I do not have the mental capacity to do so. Ironically I have been able to work more effectively than others by focussing on quality.
Coincidentally I published some of my work earlier this week. It’s an opinionated library dictating the structure of your core domain. In return it completely decouples infrastructure. This way you do not really have to touch infra at all during day to day operations, which simplifies things immensely! As the domain exists at the very core of most software projects, it greatly impacts the way everything else is designed as well.
Oh, very interesting! I bookmarked it thanks for sharing!
Bookmarked. Thanks!
I never got so far, but had a system built which some parts of what you described. It was incredibly relaxing to develop with it. Our take as a team was: boring is better, we don’t want to be paged on weekends.
Error: ‘o’ is not found in ‘S.O.L.I.D’
This is the only way;
if (condition) { code }
Not
if (condition) { code }
Also because of my dyslexia I prefer variable & function names like this; ‘File_Acces’ I find it easier to read than ‘fileAcces’
Compiler checked typing is strictly superior to dynamic typing. Any criticism of it is either ignorance, only applicable to older languages or a temporarily missing feature from the current languages.
Using dynamic languages is understandable for a lot of language “external” reasons, just that I really feel like there’s no good argument for it.
Yeah the error list is my friend. Typos, assigning something to the wrong thing or whatever is fixed without having to run the code to test it. Just check the error list and fix any dumb mistakes I made before even running the thing. And I can be confident in re-factoring, because renaming something is either going to work or give a compiler error, not some run-time error which might happen in production weeks later.
It’s much easier to work with streams of untyped data in a weakly typed language.
Even when you’re using a dynamically typed Lang you should be using all the appropriate scanners and linters, but so many projects just don’t.
I joined a large project half way through and I ran pylint and stared as the errors (not just style stuff) poured out…
I do believe that static typing is at least a local optimum, but I am still not entirely convinced. Rich Hickey is a very convincing presenter and I can’t help but think that he is on to something — with Clojure the chosen direction is contract-typing, which is basically a set of pre- and post-conditions for your functions that are evaluated at runtime. Sure, it has a cost and in the extremes they are pretty much the same as dependent types, but I think it is an interesting direction — why should my function be overly strict in accepting a “record” of only these fields?
Dynamic languages are good for prototyping, especially if a lot of libraries available
true but i dont think is really a hot take?
Agile in it’s current implementation with excessive meetings wastes more time than the mistakes it tries to avoid.
Tabs are better than spaces
Dynamically typed languages don’t scale. Large project bases become hard to maintain, read and refactor.
Basic type errors which should be found in compilation become runtime errors or unexpected behavior.
If you don’t add comments, even rudimentary ones, or you don’t use a naming convention that accurately describes the variables or the functions, you’re a bad programmer. It doesn’t matter if you know what it does now, just wait until you need to know what it does in 6 months and you have to stop what you’re doing an decipher it.
Self documenting code is infinitely more valuable than comments because then code spreads with it’s use, whereas the comments stay behind.
I got roasted at my company when I first joined because my naming conventions are a little extra. That lasted for about 2 months before people started to see the difference in legibility as the code started to change.
One of the things I tell my juniors is, “this isn’t the 80s. There isn’t an 80 character line limit. The computer doesn’t benefit from your short variable names. I should be able to read most lines of code as a single non-compound sentence in English with only minor tweaks and the English sentence should be what is happening in most of those lines of code.”
Absolutely agree, yeah
80 character limit is helpful though when you need to have many files open at a time. Maybe 100 is more reasonable. Fighting indentation is important too.
I, too, remember the days before ultra high definition ultra wide monitors.
I thought this argument was bogus in the 90s on a 21" CRT and the argument has gotten even less valid since then. There are so many solutions to these problems that increase productivity for paltry sums of money it’s insane to me that companies don’t immediately purchase these for all developers.
You have a point, devs should be using multiple large monitors. I will often need to have 3-4 files open at once, plus some browser windows. Having some limit on line length helps with this and for fighting code complexity.
The most important thing is comprehension. If something is too long and the length makes it less readable then it is too long.
But if having 3-4 files open at the same time makes it harder for you to comprehend a single file because you can’t get the full picture, that’s on you.
I have a massive ultrawide and I still 100% believe in line limits. Long lines are harder to read in general but even with a limit of 100 I frequently have 3 files opened next to each other and I can’t read entire lines easily. Line limits just aren’t about the size of the monitor and I can’t believe people still say that.
I understand the concern, but readability and comprehension are way more important than line length. If the length impairs readability, it’s too long. Explicitly limits are terrible. Guidelines, fine.
Ultimately, you do you. I still think your crazy and I think your argument is poor.
Yes a strict 80 character limit would be bad but that’s why modern formatters aren’t strict and default to 90-100.
I’ve pretty much never seen code that would have been more readable had the lines been longer than that.
My main argument is still that shorter lines are more readable. I just think it’s a bullshit argument to say that long lines are fine because large monitors exists. I don’t see how that makes me crazy.
See, I think length limits and readability are sometimes at odds. To say that you 100% believe in length limits means that you would prefer the length limit over a readable line of code in those situations.
I agree that shorter lines are often more readable. I also think artificial limits on length are crazy. Guidelines, fine. Verbosity for the sake of verbosity isn’t valuable… But to say never is a huge stretch. There are always those weird edge cases that everyone hates.
There’s no such thing as self documenting code, unless every method and variable name has the word “because” in it.
Anyone can read what the code does. The comments are there to answer why it does what it does the way it does.
Why is invariably lost to time, if it’s not committed to a comment here and there.
This is a pretty ridiculous position to take but if you believe it then I’m glad you write the comments you do.
There is an argument that commenting on the lack of expected code is valuable for this reason, but it certainly isn’t true in all situations.
We can agree on “not all situations”. Often the answer to “why did we do it this way?” is blazingly obvious, and no one wants a comment.
But we all know that sometimes the “why” isn’t obnoxious at all.
As far as I can tell, developers who do believe in self-documenting code either haven’t learned the power of “why?”, or they have a secret technique for encoding “why?” into their code structure.
If it’s the second thing, I would be delighted to be brought in on it. (No sarcasm. Maybe I’ve missed a trick here.)
I’ll answer in a couple of different ways.
-
If I am writing library code my why is you have an end use and I don’t care why you use it and you don’t care why I wrote it. You only care about what my code does so you can achieve your why.
-
If we are working on the same code we have different whys but the same what. Then your comment as to why isn’t the same as mine which makes the comment incorrect.
-
We are looking at a piece of code and you want to know how it works, because the stated what is wrong (bugs). This might be the “why” you are looking for, but I call this a “how”. This is the case where self documenting code is most important. Code should tell a second programmer how the code achieves the what without needing an additional set of verbose comments. The great thing about code is that it is literally the instructions on the how. The problem is conveying the how to other programmers.
There are three kinds of how: self evident, complex how’s requiring multiple levels of abstraction and lots of code and complex short how’s that are not apparent.
The third is where most people get into trouble. Almost all of these cases of complexity can be solved with only a single layer of abstraction and achieve easily readable self documenting code. The problem for many cases is that they start as a one off and people are lousy at putting in the work on a one-off solution. Sometimes the added work of abstraction, and building a performant abstraction, makes a small task a large one. In these cases comments can make sense.
Sometimes these short, complex how’s require specialists. Database queries, performant perl/functional queries, algorithmic operations, complex compile time optimized templates (or other language specific optimizations) and the like are some of the most common examples of these. This category of problem benefits most from a well defined interface with examples for use (which might be comments). The “how” of these are not as valuable for the average developer and often require specialist knowledge regardless of comments for understanding how they work. In these cases what they do is far more valuable than how or why.
You’ve given a lot of consideration to modern recently created code. But the best modern recent code goes on to become someone’s legacy nightmare. (The most fit and correct code survives long after anyone really wishes it would.)
In high quality legacy nightmare code “why” is lost, unless someone wrote it down.
I’ve been on both sides of that mystery. “Why didn’t they just do X?”
- Sometimes it was because X didn’t exist yet, or wasn’t matute enough.
- Sometimes it was because X is fundamentally the wrong solution, in a very subtle way.
There’s two ways to know the difference:
-
- Painful trial and error.
-
- A comment (or document) answering “why”.
I prefer the second way, but I happily charge more for the first way.
-
it doesn’t matter if you don’t know what it does now
If I don’t know what it does now my comment of “I have no idea wtf this does” won’t help me in 6 months.
This is why code review exists. Writer’s can’t always see what’s wrong with their work, because they have the bias of knowing what was intended. You need a reader to see it with fresh eyes and tell you what parts are confusing.
That’s not to say you shouldn’t try to make it readable in the first place. But reviewing and reading other people’s code is how you get better.
Let’s take this one step further. I should be able to get the core ideas in your code by comments and cs 101 level coding (eg basic data structures, loops, and if/then).
Make your app use native components instead of making your own crappy theme for the 782th time
Hot take: people who don’t like code reviews have never been part of a good code review culture.
Hot take #2: Unless you have great code review culture, code rewiews are just unnecessary blockers
I see the value, but that doesn’t mean I have to like it :p
It is also a situation in which when you don’t have them you can feel smart since you don’t have to find justification for what you do.
I am not smart enough to effectively code with certain languages and design patterns and that’s ok. There is nothing wrong with accessibility being prioritized or with making tradeoffs for the sake of reducing complexity.
what makes you say you are not smart enough? I do not think there is a “smartness” scale to design patterns.
You have to learn and conceptualize it. Some things are harder than others to learn and conceptualize. Some tasks can be easily broken down piece by piece, some you can’t do without modeling a complex system in your head. There is definitely a “smartness” scale if only because things have different demands on attention, perception, and short term memory.
Yeah I see what you mean about conceptualization + long term memory. I’ve always felt the process of abstracting things higher and higher to be fulfilling. Not sure why. But, it is very easy to get lost and over engineer and in turn not adding any value besides more stress, solving no real problems.
IMO it isn’t even that it’s necessarily bad, there may very well be a tradeoff that helps you, it’s just that the tradeoff may be different depending on who you are and what your brain can do.
Dynamic typing is insane. You have to keep track of the type of absolutely everything, in your head. It’s like the assembly of type systems, except it makes your program slower instead of faster.
My take is that no matter which language you are using, and no matter the field you work in, you will always have something to learn.
After 4 years of professional development, I rated my knowledge of C++ at 7/10. After 8 years, I rated it 4/10. After 15 years, I can confidently say 6.5/10.
Amen. I once had an interview where they asked what my skill is with .net on a scale of 1 - 10. I answered 6.5 even though at the time I had been doing it for 7 years. They looked annoyed and said they were looking for someone who was a 10. I countered with nobody is a 10, not them or even the people working on the framework itself. I didn’t pass the interview and I think this question was why.
Your mistake was giving them an answer instead of asking how the scale was setup before giving them a number. Psychologically, by answering first your established that the question was valid as presented and it anchored their expectations as the ones you had to live up to. By questioning it you get to anchor your response to a different point.
Sometimes questions like this can be used to see how effective a person will be in certain lead roles. Recognizing, explaining and disambiguating the trap question is a valuable lead skill in some roles. Not all mind you… And maybe not ones most people would want.
But most likely you dodged a bullet.
I was kicking myself for days afterwards for not doing exactly as you said. I’m not good at these types of interview questions in the moment. Also before that was the tech interview classic of asking a bunch random trivia questions, which I actually nailed. Also this was for dev II position.
I definitely dodged a bullet though. Some months later I got hired at a different company for 30k more.
Did your interviewer profess to be a 10 in .net, otherwise how would they know what that looks like? I was told that I’m unsuitable as a programmer of PLC because I never used their software before. That I write the algorithms that go into a PLC was not sufficient. These people are looking for unicorns but find donkeys everywhere they look.
He claimed everyone at dev II and higher was a 10 in their company. Complete dunning Kruger. I have no doubt I could’ve understood and worked on whatever software they have.
Ouch! Red flag. Sucks to get rejected, but maybe you dodged a bullet.
That’s a good way of looking at it.
This take gets colder as you get more experience.
The mark of a true master.
Computer hardware has been getting faster and faster for decades at this point, but my computer still slows down. Like WTF. The dumbass programmers take the extra power given to them and squander it instead of optimizing their code. Microsoft word could run pretty well on a windows 98 PC, but the new Word can slow down PCs that are 5-10 years old. Programmers are complete idiots sometimes…
Microsoft has not made a good product. Ever. Every program has issues that should not be there if you’re selling it. Yet they get away with it
Oh boy, here we go (inhales):
Agile isn’t that bad. People just believe they are more productive if they are “heads down” and not held accountable for what they write/do.
Functional programming isn’t that great and doesn’t solve all of the world’s problems; it just pushes the issues with state to other parts of your design, and doesn’t scale well in deeply nested solutions.
IDEs with proper code support (i.e. automatic structure analysis, autocomplete, etc.) are one of the best ways to deal with a large codebase that needs refactoring. Doing widescale refactors without one is asking for trouble. If you believe you don’t need it, either your codebase is just that small (which is fine) or playing with fire.
Much of the advice out there on architecture and tooling isn’t properly contextualized on the codebase, market, and team situation. If you believe you have the One True Architecture Solution, you are naive. (Ex. Microservices, large complex code pipelines, monorepos, etc.) Be especially wary of anything from FAANG engineering blogs unless you are also in another letter of FAANG.
There. Got it out of my system. Have fun dissecting it.