Things Programmers Should Never Say: “Who Wrote This Awful Code”
shubhamjain.co
shubhamjain.co
There's no merit to striving for elegance in everything you do. You're better off shipping 3 projects with inelegant kludges than 1 perfect one. The customers aren't going to care. The users aren't going to care. You ship more code and create more value. Everyone's a winner if you bodge things more!
Within reason.
Often these are conflicting goals too. If that guy hadn't shipped the kludge 10 years ago perhaps the company and project wouldn't exist today.
On some occasions the company folding would've been a better outcome for everybody involved in the medium term.
Further code is always flexible as the absolute worst case is to start over with all the lessons from the first system. However, code that has not shipped is not creating value.
I let a lot of bad decisions that "architects" made go at my last job without putting up a fight even though I knew they were bad decisions since I knew I wouldn't be at the company long term.
As the newly installed software architect at the company I'm at now, seeing that I plan to be here for a few years. I'm much more likely to fight the good fight about doing things right instead of fast.
Actually, I think doing things right and doing things fast is a false dichotomy. You can do things right, fast, and deliver the minimum viable product. I can't think of a single bad architectural decision that would help you in the short term over doing it right.
The problem with good enough is that my opinion of it differs from yours, in possibly very important ways. Good enough to you may mean it compiles and executes 'happy path' logic just fine. Good enough to me means it's at least lightly commented, the code is formatted and indented properly (sidebar: THERE ARE STILL PEOPLE WHO DON'T DO THIS!), maybe a smattering of unit tests to prevent regression, and the code is semi-coherent (no spaghetti).
Now, most of what I consider good enough has little to do with if it executes more functionality than just getting it working. But in the real world, the lack of the other things I mentioned will ALWAYS cost me more money when I inevitably have to come back to the project months down the road.
The converse is also wasteful. Don't go re-inventing a CMS because you have a couple of web forms and you want to make a universal system so that all forms can be accounted for going forward. Keep it simple, but robust. Build the couple of forms, don't pigeonhole yourself, make a note that if we get over a certain amount of different forms it may be better to have a generic system underneath, etc. Don't over engineer it. Engineer for the things you know you have to handle given the current requirements, don't engineer for the things that will happen if you reach 10x volume (you likely never will).
Most engineering doesn't need to be beautiful, performant, extensible, etc. It just needs to be done.
The most common counter-argument I hear is that this view is 'short-sighted' and too focused on 'sales'. In my experience, the short-sighted view is that you already know what you need to be building. Over-investing in the problems you know about leaves you without the flexibility and agility to tackle the problems you don't know about yet.
As somebody who's building new product off a ~20 year old perl codebase, I strongly disagree. No matter how easy the problem the system you're building to solve is, architecting and implementing a complex system that will stand the test of time is itself a hard problem. And if it doesn't need to be maintained, I would argue that you're not engineering, you're hacking. Nothing wrong with hacking, but it's a completely different approach to development optimizing for different attributes (time to market vs quality).
Now, that's not to say that they don't both have their place within a given project. Hacking together a MVP and then applying more rigorous engineering practices after it's been "proven in battle" seems to be a good balance. I'd highly recommend checking out David Black's work if you aren't already familiar, he has a lot to say on the subject! https://www.amazon.com/Wartime-Software-Building-Matters-Bet...
1) did the goals get accomplished?
2) did it get done fast?
3) did we avoid accumulating critical-path tech debt? (I'd like to emphasize that only actually critical-path tech debt matters. Tech debt off the critical path doesn't matter.)
Frankly, if you have time to build a perfect solution you've allocated too much time to the task.
Clever architecture will often beat clever coding.
Sales, as boring as they are, often pay salaries, and the bills to keep the lights on to keep. As a guy who has to pay those salaries and bills, and a developer, teaching junior and "think they're not junior" devs how to find the balance between how much abstraction, architecture and coding cleverness is enough remains the most key part of what I do.
The best devs I find, especially the super experienced polyglots, still maintain a healthy distrust of their code, think about future devs touching their work, and often write enough love letters to their future selves explaining why they did what they did.
Well written code doesn't take more time than poorly written code. Even if deadlines demand skipping unit tests, you can still write your code to be unit testable.
I'm the lead dev at the company I'm at now and basically have a clean slate and empty repo. I get to design code using best practices. I've already found that not taking shortcuts has allowed me to reuse code in a ways I never imagine.
I don't want to curse my 2017 self out in 2020 because of bad decisions I made.
True in 2020 I might look back on decisions I made in 2017 and kick myself, but I will have small focused microservices, decoupled classes, and a full suite of automated tests to allow me to refactor aggressively.
Even to the point if in 2020 I decide that one service should be rewritten in TrumpScript, I have automated Newman API tests that will allow me to rewrite the whole thing and have a level of confidence that it will work.
I get the chance to instill a culture of doing things right is more important than doing things fast.
$ git blame
Oh, I did.Who among is hasn't written code that, upon review, made us cringe? (Maybe a lot. Maybe just a bit.)
When you complain about code, instead of making constructive critiques, you aren't actually doing any one any good, least of all yourself. Instead, focus on what is good about the code and the opportunity to improve it that has just presented itself.
During the problematic code section if I was harsh they usually knew it was my name they were about to see in a commit log. It was a dramatic effect to prove the point: even the people who are supposed to be championing quality have a bad moment for whatever reason, no one is safe from shitty code or bad ideas and executions, and anyone can write something elegant and sneaky awesome. One bad commit doesn't make a shitty engineer, so don't go calling everyone else's code garbage. If you're really as good as you think you are you can fix it.
But just like when we have an outage, we don't just repair the problem, but we try to fix the conditions that allowed it to happen, I think when we find bad code (and especially broken code), it's valuable to understand what practices led to that and try to improve them. That means pointing out when code was never tested or when obvious edge cases were missed -- or any of the explanations listed in the post. Sometimes, the lessons are deep and important (like the relative value placed by the team on developer's time vs. QA's time or Ops's time).
Oh, but the only reason I'm currently reading that awful code is that it doesn't!
1. I wrote it and it never worked.
2. I changed something and broke working code.
http://www.dgp.toronto.edu/~karan/courses/csc2529/cartoonlaw...
So yes, the code was shit, but the coders weren't.
Writing poor code when under constraints is understandable. But there's bad code and then there's bad code. There are very different ways to write code that isn't ideal, but some forms cause far more problems than others. I think it's very dangerous to give a blanket OK to all bad code as if there is no difference.
Not to mention, feedback. If I'm doing something awful in my code, I need to know, because I'm likely doing it because I don't know a better way. If I wrote it that way because there were constraints, then I can explain the decisions in the context of those constraints, as well, but there is nonetheless a standard I try to hold myself to even if there are constraints.
This kind of thing is very subjective and comes down to the specific situation.
"Oh, shit..."
I was trying to figure out a mass of javascript that was being used in a Business Catalyst site I was hired to add some features to, and I eventually realized I wrote it for a prior job for the same client months earlier. It's a weird experience.
And every time it is a great learning experience.
Usually it's more, yeah this code sucks, there were these constraints during development that made it a good idea at the time.
Example: Suppose you have a requirement to display times in a zone different than the system time. Simply appending the new time zone offset at the end of the existing time stamp should prompt obviously would not accomplish that. It should merit at least a private invoking of "Who Wrote This Awful Code?" if someone comes upon it in the code base, followed perhaps by "Why am I the first person to notice this?"
The first question might answer why something that silly came into being. The second question can help you decide between fixing it or just cutting it if nobody noticed it was broken that long.
1. Write beautiful perfomant code per specs, no cutting corners. End result: Product was late, later scrapped and the entire division was laid off 2. Cut corners to reach deadlines. End result: Still playing out right now, but I'm glad we have something that "works" rather than 1. which is lost in history.
I'll err on the side of 2. since there is nothing perfect and it's best to get something out rather than chasing a unicorn that doesn't exist. I think as engineers we forget the business aspects of software development which whether we like it or not, is a reality.
Sometimes, it's me looking at someone else's godawful mess, but then I try to use tact.
It was coded by experienced contractors at great cost whose entire body of work I have judged to be far below the reasonable standard of a competant developer. I've actively called for them be sued and have costs returned several times.
Although rare, as professionals we're subject to a professional obligation to weed out the most reckless of our community. Anything less and we risk being knowingly dishonest.