I appreciate that laundry list can contribute to writing good code, but I kinda wonder how much that has to do with it vs ... just not writing good code, for some other reason (time, bad incentives).
I've only been coding professionally for a handful of years, but I feel like I see a lot of reliance on various ideas and systems to produce good code. Programmers seem to think that they can enforce various systems and ideas to MAKE people write good code . While I think those can help, often I think those are used as all or nothing type measuring sticks.
Personally I think an individual programmer's choices are more (or maybe less) complex than that, as are the outcomes, regardless of some laundry list.
This explains a lot of my interactions with my peers. Some groups of developers need hand holding, guidance, feedback, and correction. Continuously. The other group just gets stuff done and get normal feedback I”d expect from my own work. When one of the first group complains about code, I try to explain why it’s written that way. When the second group complains, I ask what we can do to fix it. Amateur vs pro may actually be a useful distinction here.
Sometimes this is a serious nightmare. Some younger developers think that pair programming is a given and that they expect that someone more senior will be developing with them, which often ends up you doing all the work because they don't understand even the basics. I know some people love it though, because they feel "better" and they have their little "being a teacher" fantasy going, but I try to leave such place as soon as possible.
Definitely agree! Nowadays many developers skip over the design patterns, thinking abstractly, etc which over times causes technical debt.
Many companies have very good processes in place and the above does not hold true for their employees. I was once at a company and was blown away with how well their code was structured, processes, etc I literally had no work to do (very rare).
One of the problems I faced is that the university didn't teach TDD, I couldn't find any books about TDD and every single programming course didn't even have a section about TDD. It's like this was some kind of secret knowledge that only few had. I was only able to learn TDD when I joined one corporation and it was like a new world to me. I tried to learn as much as I could and then carry that to next jobs.
It's better now, but I feel like this knowledge is somehow still not shared as much. People still, when they create a course, they commit little time to testability and explaining how you can validate what they say.
I find it frustrating then when new people come to work, they severely lack testing skills and that is not a fault of their own, just there is very little real world examples and tutorials.
Some open source projects have good tests coverage so that's a great way to learn.
On the flip side, as a dev with 10 years exp, I think TDD is a process crutch designed to cover up poor engineering by adding additional time spent to all work.
Yes and no. At $WORK we started using a security scanner and I'm triaging the issues. It's definitely a box ticking thing. OTOH I'm finding real, concerning issues.
There are people going for 100% coverage and pedantic unit testing so that it only works with that particular implementation they wrote and then when you want to change something, you'll have a pile of tests to change that don't add any value. Something like this we try to get rid of.
I guess it depends on what time period you’re talking about. There’s a million books on TDD and there have been for decades now. They’re commonly recommended on HN and easily found via google.
The TDD advocates I have been exposed to are mostly cargo culting consultants and this alone makes me very sceptical. It has some good core ideas but I find that in practice it leads to unit tests that are highly coupled to implementation details. Quick to execute but almost worthless from a test perspective. Its best to throw them out after the inital implementation is done since the usually just become a burden to maintain. Black box at system boundaries are the only tests that bring value long term in my experience. I would really like to hear more details about projects that use TDD and how they use it a few years down the line. All I can find are toy examples..
Project I work at right now could really benefit from basic TDD principles, mainly just setting test / outcome matrices and basing production off of that (which logically follows into TDD). The requirements are largely set up front, yet we still shoehorn unit tests in after production is done, wasting both development and test time. Requirements rarely change in major ways, and they are often established months up front.
Other times I work on stuff where fundamentals change rapidly. At that point I'm spending 1.5x-2.5x the time just to include test I'm likely to remove, and TDD largely inflates time required I don't have or wish to spend. Often testing trivial things, too.
Most devs switch jobs in 2-5 years (or at least that's the common advice given). So the incentive is to play musical chairs, and hope that you've moved on by the time the music stops.
Software has also been such a new field that it was the startup that moved fast and broke things that got the prize rather than the slow but stable company. I think this is changing (lower barrier to entry and ever-increasing complexity). But the momentum still exists.
Further, management notices and rewards the developer who is chewing through tickets, especially when those tickets are visible, user-facing features. If those developers are sloppy (and they tend to be), the bugs, readability issues, etc don’t get traced back to them and the rest of the team gets no glory for cleaning up after them and actually productionizing the prototype-grade shit they deploy to production.
I chewed through tickets and regularly had an above average point score every sprint, even as a brand new junior developer. I sometimes had the highest on a team where everyone else had 5+ years of experience, which should have raised red flags. Heaps of praise though.
And I was doing it by taking the most direct path to it working without really knowing the potential consequences (which I didn't understand at the time).
The guy who wanted to do refactoring didn't get his contract renewed as that was not productive work.
Also there can be other real life business constraints. Sometimes the project need more devs but there aren't any to add. Sometimes the deadline is truly set in stone and if you miss it you are truly fucked. In times like these you have to cut corners and these are the easiest corners to cut for short term speed.
"Amaterur vs professional" feels "Good vs Bad" for me but real life is never as simple as that.
Software today is a complicated mess. On the consumer side, peoples minds are so fickle and they want the latest shiny object or app; on the software side, companies are constantly inventing new ways to do the same old thing; hardware is getting tossed in the dump, when it is actually still very viable.
It's fascinating to see what people are doing with old hardware like Commodore 64, because it's understandable and doesn't change at this point. If we can use hardware that is almost 50 years old, why are cycling through things so rapidly?
OTOH, business itself cannot spare any manpower to maintain old code.
Not their fault either, because maintaining old code is hard, frequently will introduce new bugs, and potentially halt business. Less hope for migrating into newer engine / language.
It's simply that software development is hard and we lack standardization more than any other industries.
I think the heart of this isn't devs changing jobs. It's execs. I know plenty of devs who will be "irrational" about quality in that they build for sustainabilty and longevity far beyond their personal economic incentives.
But when those same devs go up the chain to improve practices or clean up tech debt, they rarely end up happy. I think that's because executive turnover is also fast and the rewards for underinvestment are much larger. Executive compensation is often tied to stock price and other short-term metrics, and executive tenure is also quite short. That gives them a strong incentive to cut anything that pays off over the long term.
Which I think ties back to his professionals vs amateurs thing. One thing that distinguishes professionals is standards. Doctors won't prescribe you anything you want. Real engineers will refuse to build things that will collapse. But a lot of devs are more minions than professionals; if the boss says to build X, they'll build X. Whether that's good for the company, the customers, or society isn't relevant.
I've rarely seen progress get made when it's framed as "I want to clean up tech debt." To execs it seems like moving deckchairs rather than moving the number (which to be fair, it sometimes is).
"In order to release feature x which customer y cares about, we need to clear up tech debt / refactor z" is a much better way of getting execs on board.
Excellent point, it needs to offer a concrete benefit. Simply saying “it will make it easier to write new features going forward” won’t convince anyone.
For sure. That's definitely where many organizations are. "To cook breakfast this morning, I propose we clean up last night's dinner mess. Here is my 27-slide deck."
But I think it's also worth orgs getting to the point of defaulting to just cleaning up after dinner, and also cleaning as they cook. Having to have a specific, urgent reason to clean up a mess is a fine argument for 13-year-olds to make as they come to understand how a household works. But it's tiresome when nominal adults refuse to accept that the future eventually arrives.
Being irrational about quality does not lead to easier to maintain software. You need to be rational about it and the distinction matters a lot.
You can go all petty on minor idioms and force everyone to use all the sonar rules and all it will create is a lot of busywork with zero improvement on maintainability. And I have seen this dynamic to happen more then once.
That's not the kind of irrational I'm talking about, which is why I put the word in quotes and then explained exactly what I meant in the same sentence.
I wonder how it applies to most sports. I think the amateur strategy of "don't make as many mistakes" applies to professional team sports too.
I can think of a lot of successful professional teams who for the most part simply outlast their opponent by not making mistakes and capitalizing on their opponents mistakes.
American football for sure often has games turn on a handful of plays.
Also seems like it would apply to most competitive games. Like I can easily see the same concept applying to Chess.
Looks like this is the Loser's Game essay he mentioned, btw. Also looks like in that essay, it's less about tennis and more about basically doing what the OP did, but applying the metaphor to investing: https://www.trendfollowing.com/whitepaper/the_losers_game.pd...
I've found a lot of lessons can be drawn from competitive games with tight feedback loops and applied outside of those domains. There's something to be learned from these areas where there are a whole bunch of people trying very hard to get good at something (e.g. chess, Rocket League), especially with regards to how to build a mindset around failure and how to review your mistakes.
The hard part in all of these is finding the right "hooks" in these pursuits that tend to be more obvious in competitive games. How do you "record your performance" when programming or holding meetings about business strategy? How do you review that recording after the fact? What criteria do you use to evaluate success and failure?
It's certainly not as easy to do this with "games" that lack a clear scope like startups, but I've found regularly reviewing your performance ("Did this meeting have a clear agenda before starting?") and building checklists for what practices lead to success is immensely helpful.
For a long time I've wondered if it'd be a good idea to have my deploys look at the test coverage and refuse to deploy if it falls below a threshold. I think it's a good idea but I know it'd annoy the hell out of me if I actually implemented it..
I think error budgets are an excellent idea for this type of tension.
Release crap that breaks too often? OK, you have taken too much of another team's resources, and will have to release less and/or check your work much more carefully.
Release something that might look low quality to an outsider, but that actually works perfectly well? Fine - no negative consequences if nothing bad happens.
This is fine when errors have clear boundaries or the system is more or less trivial. It's easy to have clearly defined error budgets and assignment of blame. In more complicated systems (e.g. mature companies or complex architectures) the assignment of blame becomes problematic, and that makes the tool (error budgets) less useful.
This removes so much headache in the long run. Often by writing tests you discover something not considered before and that improves the product a lot and its stability.
I have some projects that have been online for like 4 years now without reboot. They have very good coverage.
I hate going through logs and debugging, and I almost never do it after committing to testing. Things just work.
Honestly it is hard going from no code-coverage to a rule of at least x% of code coverage. Instead of adding a blunt rule I went with something different:
Some years ago I've implemented a check to fail the PRs if the lines touched on that PR don't have code coverage (delta-coverage = 100%).
We aligned internally with all the affected developers and went with it. We defined that the rule is that 100% of the code needs to be covered, but it doesn't mean that the rules can't have case-by-case exceptions. Whenever someone needs an exception the teams gets together and approve an exception. Sometimes it is a backlog to write the tests later, or some files that don't need unit tests altogether.
This may have worked for us because we are 5 years into this codebase and it keeps on growing, but for more small projects this may be more hassle than it is worth.
Honestly, after the first 6 months (not easy, not gonna lie) I felt better about the codebase, and I love the confidence of trying things and having unit tests all around. There were times where I submitted a PR and forgot altogether to write tests and this rule caught me.
I recommend it, but as with any software development practice, this is not a one-size-fits-all game.
It looks like the kind of obvious linkedin article young people write after reading Clean Code :D
I'd be more interested in project size, business pressure, cost incentives etc to explain why software always grow to a direction that seems to hinge on the unmanageable.
For instance I agree and implement all he says, but let's take one example: we can love unit tests, and I never push something for review without many, but there are fundamental limits to them: you can assert wrong in many ways without any kind of measure beyond coverage, you can make the same mistakes in the tests as you did in the implementation because you just misunderstood the business, you can rush a solution to solve a problem happening yesterday, and test half of the problem etc.
So doing unit tests ONLY won't save you either.
My 2 cent would be to make us users of the software, that would really help move towards stuff we stuffer tenfold the limitations and failures of. Adding unit test in the process is the absolute minimum (so I agree amateurs only should dislike them), but still just the minimum to get anything serious out. The maximum is to make us the clients, or them the programmers. A direction we discuss in investment banking where we fire traders to replace them with people who can launch profilers during automated trading.
Software developers are just responding to incentives. Managers/Product owners want features and aren't too bothered with defects, as the idea of bugs is so normal now. Do they care about defects? Yes, but only if the cost to fix them doesn't change the deadline.
Nobody cares about a bug unless it's highly visible or dooms the product, and would rather you just cram feature after feature in. Nobody's ever been promoted for great work maintaining the old version, or for reducing our bug count by 50%. The result is a product that you cannot be proud of, because it's literally the worst thing that the customer will still buy.
Yep, totally agree. Writing quality code is always on my mind but when something needs to be delivered yesterday what are you going to do? Options are: delay the release or release it with the crap we wrote
An ask of anyone reading this article: Please don’t let yourself become a smug or cynical programmer.
Too many programmers read articles like this and assume that they are the 20% of good programmers while everyone who disagrees with them is the 80% of amateur developers:
> I have worked in software development for 20 years, worked on many projects with many software developers. I estimate 80 percent of software developers are amateurs and 20 percent professionals
Yes, it’s true that some programmers deliver better results than others. It’s also true that some have better methods than others. However, this is one of those situations where if you pulled developers aside and asked them to rank themselves relative to their peers, you might get 80% of people rating themselves as above average and 50% of people claiming to be in the top 20%.
A common pitfall I see is when developers forget that the goal is to ship software and instead focus on doing everything the most correct and perfect way they can think of, regardless of their resources. I’ve worked with many teams of professional programmers who spent so much time perfecting their tooling and code and architecture that they rarely ever shipped anything. Learning the tools of the trade is important, but don’t lose sight of the goal: We need to strike a balance and get work done, not just perfect our craft in a vacuum.
And the people claiming to be in the top 20% are going to medium and post a blog post about it.
I mean, he's not wrong.. but I always get suspicious if somebody is making up percentages. You know 90% of percentages are made up? (Yes I just made that up)
Yeah, I think it’s dangerous to try and say that there are 2 groups of people here. Instead, just say we are all amateurs and there’s no reason to take off the training wheels.
These articles are intentionally written to satisfy that "I'm a better programmer" itch. Everyone imagines themselves to be the better programmer, and will always have a laundry list of reasons why they're just "better". And people will post it on twitter and LinkedIn, etc, under the rather pathetic guise that it will demonstrate they they are the professional.
There's very much almost a meme of those programmers who tell us all how everyone else is doing it wrong ... but their whole idea about who is doing it wrong seems to be entirely driven by how often they're inconvenienced by other people's code, but never account for how often others are inconvenienced by their code.
I get inconvenienced by other people's code all the time, but it's so easy to assume when you're looking at the bug "they should have known this was going to happen / tested for this" when you started your investigation knowing the trigger for the bug.
Anecdotal story: I had a bug a few weeks ago that all sorts of people thought was really dumb / obvious / shouldn't have happened. I checked... the code hadn't been changed for FIVE YEARS. Nearly every customer we had ran this code for five years. Maybe I feel that they should have had a catch for the situation that occurred, but whomever wrote it wrote code that lasted bug free for five years ... maybe they weren't dumb and they knew something I didn't?
One of the best experiences I had that humbled me was getting irritated by the inconvenient/obscure code I was dealing with. It was clever as hell, but impossible to understand and even harder to work on. It wasn't buggy but we needed to add a new feature and it clearly didn't anticipate that. I spent hours cursing the bastard who wrote it. Finally after I was done and checked in the changes, I looked to see who had written the original code. It was me.
Oh yeah, I’ve done that one a few times. However! I’ve also had a couple of cases where I was really happy with whoever had written something only to find out it was also me. Very rewarding.
Indeed, that has happened to me as well. I chalked it up to me just liking my own style though. But yeah it's awesome to work on code I wrote and think, "wow, what a thoughtful design!"
> I get inconvenienced by other people's code all the time, but it's so easy to assume when you're looking at the bug "they should have known this was going to happen / tested for this" when you started your investigation knowing the trigger for the bug.
When I was a junior dev I had a tendency to want to rewrite everything. I remember thinking that most the code I was working on at the time was overly complicated and could be done with far fewer lines of code. Recently I realised I might now be the guy that now overengineers and writes overly complicated code. I think this is common trend for devs too, as you mature you get really good at anticipating future problems so tend to write code that doesn't just meet the current requirements, but can scale into likely future requirements.
I feel like I've kind of gone full circle and now and I'm starting to question if there is a middle ground between the simplicity of writing simple code to solve a very specific problem and the extra time required in writing code that scales. The reason I say this is because I realised devs working on my code often don't fully understand the reasoning behind what I've written anyway and I and the devs working on my code often don't have the time to read / produce documentation explaining the code in detail. I also can't guarantee I'm always available to review PRs and ensure the code quality is maintained, so perhaps most of the time it's wasted effort.
Also often you just don't know what kind of constraints devs are working under. I know for a few projects with tight time constraints I've been asked to do the bare minimum to patch certain bugs or add some functionality so we can ship ASAP. I'll normally push back on this if I feel it's a bad idea, but code quality isn't always the most important consideration.
I realise I'm much more open minded when reading code now because after 15 years as a dev I'm still not sure I always do things right myself.
> Anecdotal story: I had a bug a few weeks ago that all sorts of people thought was really dumb / obvious / shouldn't have happened. I checked... the code hadn't been changed for FIVE YEARS. Nearly every customer we had ran this code for five years. Maybe I feel that they should have had a catch for the situation that occurred, but whomever wrote it wrote code that lasted bug free for five years ... maybe they weren't dumb and they knew something I didn't?
I've seen this. Huge big O complexity but on a dataset that fits in cache? Runs fine. As soon as the dataset gets bigger, you get systematic timeouts.
Maybe I'm weird but I think I am pretty average at programming. Not great, not terrible. I get things done, more slowly and with more bugs than some, more quickly and with fewer bugs than others.
Of course most employers probably aren't looking for an "average" programmer, but I haven't found that they usually ask me to rank myself relative to others.
Their idea of average is going to be unique to that company. If they've got some objective test that ranks you accurately, they've got a multi-billion dollar process on their hands. If we had this test, we'd know what to train for, and we'd all become the average developer but write less bugs and better code. It'd become the standard test for developers.
In many cases, companies just want you to sell yourself and hear the right things. Most companies know they can't hire a senior FAANG developer for $110k.
It's also possible to try to strike a balance and to get it wrong. It is also possible to strike the right balance proportionally but be in a business environment where your best effort results in failure.
I am one of those that can’t get started because perfection and peer review is in my head. I blame it on Stackoverflow making me feel like a moron every time I ask something.
Its a toxic, anti-enlightenment culture, if any question or request for information is perceived as a attack on the self-worth of the author of that piece of information. I think at the root of this perfectionism, are loads of damaged individuals, whos whole identity and self-worth is defined via their work, their code, their child of mind.
There are so many of these, that they can become a culture majority and bring whole projects to a stop. When i encounter these, i tend to isolate them, link up with other reasonable people (who usually also work around them. If they have grown to powerful, you build two versions, one with their "architecture" (which they will inevitable grab and sink years of time into) and one that will be actually shipped, as a emergency solution.
If discussion is not possible, double the project estimate, cause there are two now.
> developers forget that the goal is to ship software and instead focus on doing everything the most correct
I'm far, far more frustrated by developers who focus only on shipping software and making dates by cutting corners wherever they can and leave everybody else to deal with their gigantic mess later.
I see this as a false dichotomy - the real most correct way is less expensive, it's just that quite often people who think they're aiming at perfection are instead actually experimenting with different approaches at random with no clear benefit.
You don't need to cut corners to achieve cost effectiveness and tech debt is just that - debt, which always has to be paid eventually - either through expensive bugfixing, a rewrite or bad user experience.
The project's I've been in that went over budget usually had one or more of the following:
-Too large of a scope vs budget.
-Bad or no architecture whatsoever.
-Increasing personnel instead of reducing scope.
On the other hand projects with an architecture, a set of clear conventions and flexible scope fared much better.
Focusing on fixing bugs and maintainability can make a project substantially better long term.
Though I am not very keen on the underlying reasons the author gives. Seem to be anecdotal and not cover a host of other situations the solution could cover. I think there can be many other reasons. Cultural for one.
In the example of the professional team they may still be beholden to write cheap code because of certain business decisions, despite tests and the fanciest of ci builds. Additionally ‘amateur’ teams could still produce high functioning websites if there goals were shifted toward leaning and measurements taken against customer satisfaction and reduction of bugs over time.
> If we invert software development, the goal isn’t then to write code that works, it’s spending time on avoiding writing poor quality code and bugs.
This line is packaged to sound really insightful, but is it?
The goal of software development is to create software in support of some greater mission. That mission might be to make someone's life easier, to make money, to advance human knowledge, or many other things.
If I write no software today, I've also written no new bugs. But have I made any progress toward achieving the mission?
Feels like this person is very frustrated with novice engineers writing buggy code and has assumed a gatekeeper role to protect the integrity of the codebases in which he holds responsibility. It may be a necessary role at his organization, but I just don't agree with the cynical and depressing message.
Agreed - this article reads like a "get good" message to "amateurs". Which, sure, you should be striving for constant improvement - but if you work in an environment where sloppy/quick work is incentivized I would argue it's the responsibility of the "professional" to push back and set up an environment for success.
Blaming all your issues on more junior members of the team is a huge red flag, and this article doesn't really offer any insight into how to bridge the gap between "amateur" and "professional" (which, imo, falls on the senior members of the team).
I agree junior members should be helped. Lots of developers have a cowboy approach but they aren't junior.
Senior members should set and enforce the standards via best practices, code reviews and setting the definition of done e.g. unit tests, data, deployable etc
I always read these and wonder "So uh, did you go and talk to the guy and help him out?"
Now maybe they did and the other person refuses to listen (not common in my experience), but I always wonder... you can't just make up 'rules' and expect folks to magically write good code because they followed a rule.
I feel like it’s the word ‘goal’ that makes one stumble here. I agree that he is not really describing the ‘goal’ of software development. He’s describing how to succeed at software development in order to reach a larger goal.
And although it took me a while to understand what the author is getting at, I do kind of see his point which in my mind could be summarized as: slow and steady wins the race. Or: In order to speed up (in the long run), slow down (in the short term). Be conservative, be thorough, understand that developer productivity isn’t about that LOC per x unit of time.
One analogy that comes to mind for me is Formula 1. Sure, it would be faster, right now, to just not pit. You would have to drive into the pit, stop and wait for the tyres to be changed and drive out again. Meanwhile your opponents are zooming past you out on the track. But if you don’t pit, soon enough your tyres will be worn down and it becomes impossible to keep heat and performance in them, and after a while longer you might even have to stop completely due to a puncture.
The ‘pitstop’ could be anything that ensures productivity in the long term and as such helps in reaching the final goal, and those are the things that take a professional to understand the importance of.
I understand where you're coming from, but I'd read it as writing code that will behave the way it's anticipated without any gotchas - merely writing code that works in a specific scenario shouldn't be the goal. Additional benefit would be to write code that easily extendable, but that's not mentioned here.
> The goal of software development is to create software in support of some greater mission
If that's the goal - the only goal - then all code is equal, and it doesn't matter how it's written. So... go crazy? Use global variables and goto statements? Hardcode path names and don't bother with build scripts? Writing software that works is challenging, but writing software that can be safely modified is even more so.
Right, but in most cases, supporting a greater mission is a marathon, not a sprint, so bad code in an early version is very painful later, and detracts from the long term mission.
I mean, if the only requirement is "have software that works", yea, go nuts. Look at a ton of tech demos, working is the goa the goal, the code sucks, it's fine, it's gonna be rewritten anyway.
Practically the requirements are "have software that works, and will be sustainably developed and improved for 5 years". Making the trade offs in terms of "perfect code" to "good enough code" is what makes a software developer (in most settings) go from "good" to "great". Good software engineers can see all the edge cases and future paths. Great software engineers can prioritize those against business goals.
Just like "global variables and goto statements" is bad, so is "perfect, provably correct, and overtested" code in the vast majority of business settings.
I think you're right, but I also think the author isn't necessarily wrong.
Using his tennis analogy, each chunk of code written is like swinging at the tennis ball. You don't have to have the perfect curve-ball, you just have to NOT screw it up.
I've too often seen developers try to attack the ball with the perfect swing and the most force possible, only to have it go straight into the net. If they just focused on getting it over the net as simply as possible, the end result usually means less code that's easier to understand.
Example: junior dev needs to write a data transformation pipeline. They write a microservice and deploy it in Docker on Kubernetes. They do a lot of hand-wringing about reactive design and non-blocking I/O. They end up wrestling with the deploy and getting it done on time. All it needed to be was a simple single-threaded command line utility.
In 15 years, I've seen this story play out tons of times... I'm basically watching devs trip over themselves. I'm not saying I'm perfect either, this has happened to me too.
This reminds me of advice I give to junior devs who over-complicate things in the planning phase: "Start with the stupidest thing that will work".
You need to make something work before you can make it work well. You need to start simple before you dig into the complexity. Sometimes you find that the "stupid" solution is good enough.
I think it's important to note here that you need to start your thinking or design from the simplest possible solution, but that doesn't mean it always makes sense to actually implememt that solution.
Agreed. That's why I advise to start simple/stupid, not necessarily deploy the stupid solution. It's a direct response to those who start out with crazy-complicated schemes in mind.
I wonder if there is something going wrong in the software engineering education pipeline that is encouraging developers to always keep reaching for the most complex tool in the toolbox rather than the simplest. We all see this all the time, so the problem is widespread. Maybe it’s not education but career growth: It sounds like “resume-driven development” where people are incentivized to add complex tools to their toolbox merely so they can get hired at places that select for complex tool use.
I think it's just inherent in the personality types that are successful at software. We are good at understandinging complex things, and we like it; it makes us feel good to master them, and creating one is a special variety of mastery, so we incline towards that.
I think it also takes experience to see that simple solutions can be more robust; the more natural response to foreseeing future problems (another trait) is to have specific responses for all of them, which generates a complex result.
I hear this often, and I see many on HN be in favor of this narrative, but I have the opposite experience. Its often the cargo-culting companies pushing these soft requirements onto education, as students and companies will otherwise complain about not being employable / finding starters who reach their expectations respectively. Most of the time, I see seniors reach for overly complicated solutions, when much simpler solutions exist. Which later falls apart when errors happen silently and simple ideologies like "single truth" are ignored for no particularly good reason, leading to massive duplicate code and gotchas.
At this point, I'm extremely unconvinced the problem is just education or juniority/seniority. The "paper factory" is just doing what companies are demanding. The real problem is a general lack of competence being used to market products, be they good when used properly (e.g. GoF, where many readers only look at design patterns and completely forget "composition over inheritance"), or snake oil.
Sometimes people haven't been exposed to different ways to solve problems, so they reach for the first thing that comes to mind. Sometimes the never learn to consider multiple solutions and weigh their costs and benefits.
I once had a boss who still coded, even though all the developers begged him to stop. His code was spaghetti, but worse was his inability to come up with more than one solution to a problem. If the first solution he came up with was complicated and error-prone then that's the one he proceeded with.
In my experience the most common cause for this phenomena is that the devs are afraid they won't be employable if they don't utilize those fads or, as you very correctly summarized it: resume-driven development.
> This reminds me of advice I give to junior devs who over-complicate things in the planning phase: "Start with the stupidest thing that will work".
> You need to make something work before you can make it work well. You need to start simple before you dig into the complexity. Sometimes you find that the "stupid" solution is good enough.
100% true.
People love to dig at Test Driven Development, but it solves a common problem and is great for junior developers because it has 3 important rules.
1. Understand your requirements. And not in a wishy-washy hand-wavey way. But in an explicit, expressed as a single test verifiable/falsifiable requirement.
2. Implement the simplest solution that meets your requirements. Don't over-engineer anything, don't chase the latest fad, don't sleeve solve a way more complicated generic problem that you think we'll hit later, because you don't have enough experience to know how likely we are to hit it and the costs to make that tradeoff.
3. Keep you codebase clean and well factored. Don't let cruft and hacks build up.
Ignoring TDD, any junior engineer that can consistently exhibit those three behaviors is almost by no longer a junior engineer. Those are hard things to learn as an early coder.
Yes as you become mid-level and senior you should be more independent and break the above often - but at that point you have good foundations and the experience to make the tradeoffs to know when to deviate and by how much.
TDD is a very effective method for solving a problem that otherwise often takes a while to solve. Developing good fundamentals.
> 3. Keep you codebase clean and well factored. Don't let cruft and hacks build up.
I feel obliged to mention that this very often goes against "do the stupidest thing that will work".
Most of the time in my career a clean codebase has naturally led to an intelligent solution which is definitely not the stupidest thing that will work.
Finally, it's also often the case that stupid code requires exorbitant amounts of comments or documentation, undermining the notion of it being simple to extend (which many conflate with the original premise). A little bit more intelligent code is usually self-describing.
>If they just focused on getting it over the net as simply as possible, the end result usually means less code that's easier to understand.
I'm sure there's some range of nuance to your point, but it's also in line with the iterative philosophy isn't it? Do you find patching/revising things later to skew better/worse or some other downstream consequences?
It seems like you find that approach more efficient overall?
This is a fault of the team culture if it allows junior devs to do that.
The whole point of design reviews, code reviews, senior devs, and more is to ensure that stuff that doesn’t work or can’t be maintained doesn’t get deployed.
> ensure that stuff that doesn’t work or can’t be maintained doesn’t get deployed.
That part (especially the second: maintenance) is endlessly contested in calls until some of us just give up and let the others reinvent the wheel for themselves because they don't listen to experience.
What is the alternative? If you let shoddy code in, it is difficult to get rid of and it may become a foundation for even shoddier one (if you let that in, then why you won't let this in).
I didn't read the article the same way. I think we're all, in a certain way, amateurs, at least in some cases: when we're rushed, stressed, distracted, or all three. As a project accumulates people working on it and, crucially, as existing code is modified and added to, the probability that you'll introduce a bug approaches 1.
I think the article is saying we should focus on tooling that makes natural human errors less likely, instead of trying to focus on writing more code: in other words, write less code, ship it once without errors, instead of writing more code and having to go through the dev to prod feedback loop repeatedly. The tooling that helps you do that are DevOps practices, testing (and testability), simpler/more conservative design, and some time spent thinking about how to construct the software (or reconstruct it, when modifications are needed).
> Feels like this person is very frustrated with novice engineers writing buggy code and has assumed a gatekeeper role to protect the integrity of the codebases in which he holds responsibility.
I wonder what his recruitment pipeline looks like where 80% of engineers end up not being productive.
Experienced developers use their good judgement to apply the right amount of these kind of things where beneficial instead of blindly adhering to these rules.
Big fan of Tom Gamon's Programming is a Losers Game (Sept 2020)[1]. Tom's short post was a very welcome introduction to the matter for me, very open ended, & Ben Hosking here elaborates much more clearly specific concerns & outlooks.
Both Ben in this "Software" and Tom Gamon in "Programming" anchor their arguments to Charles Ellis, & his example of tennis as a game where the talented score points, and amateurs inflict self harm.
Both of these articles espouse a similar, conservative minded viewpoint that maintaining & supporting is a more key or perhaps just more-absent activity than progressing. They warn that devotion to progressing/going out and winning often brings about doom & trouble. They speak to us of the hazards about, that the paths available to the software's future becomes confined or the ground unsteady if we don't take our software environment seriously.
I'm both very sympathetic to this software-conservatism , because (a) legacy systems/the past rule so much of the software world, and (b) we certainly do make confounded mistakes a lot, but also deeply worried about what it's done to our moral character. Software isn't eating the world anymore: it's past that now, that's past tense. Software has eaten the world. At almost everyone company you go to your world will almost entirely be already consumed by mounds of existing software, upon which the company is most often busy accreting new layers of software that will shortly settle into place & likewise become buried. It's a frank truth that minding your environment, trying to insure some safety & quality to the layers is critical, the belief that we should/ought/must build solid baseis extremely valuable here. But I somewhat fret programmers have been tamed into minding our own loser-dom, am concerned that we stop looking up to the stars, when we stop being brazenly brave. We have immense immense powers, and from so many camps- within the programmerhood & external- I see a reaction of panic, & fear, & distrust to potential. Which is both warranted, but also really quite besides the point, is too often too strong a diminishing force for great potentials programmers have such keen great sense for.
I feel there is an over-regulation, an over-pressuing on our social systems these days. "Overnight Pizza and the Consistent Unreliability of Expert Guidelines"[2][3] is recent article ostensibly about Expert Opinions & the low-information-density environments such guidelines are crafted in & for, but it's also an incredible story about social pressure, the urge to be right, about the emotional high one gets from being certainly completely correct &
proper & everyone else being a fool. It's about overly absolutist perspectives, that don't allow for a bigger continuum of opinions. And I think a lot of software folk have turned in to the "overnight pizza will kill you" camp: they have encountered some parts of the maelstrom, tasted what the uncivilized is like, and their reaction is to build & fortify against the encroaching dark, to turtle up, & build strong best practices & robust processes. Which is both noble, respectable, given the maelstrom of software, but also... I feel like our lack of adventurous spirit often holds us to petty tasks, and keeps us from exploring & seeking better lands, with much richer yields.
This is very well put and am surprised it didn't get more replies.
>Only rarely does the business let us drive towards the true fantastic excellences that we dream of pursuing. Just as the business doesn't understand the loser's game challenges that are all over the place, oh, sad, the business also does not have anywhere near the vision or creativity of the individual, of the coder, who sees possibility & value oozing out of so many areas, often so untapped. And programmers are not put into decision making roles nearly enough, not given structure & the attitude that they can strike, that they can chase down big game, game the rest of the company often has a hard time seeing. The socialization processes that work places must go through to allow commitment are very high, and so programmers simply do not have the time, ability, or often even the common language to get the businesses play the winning game. We must trust that the business somehow is aligned to let us make them kings, rather than taking an active stake in pushing the business towards their would be kingdomship.
The socializing aspect is spot on but there is also a fear that the business people have of losing control. On the software domain they are clueless and they prefer to keep the reigns, even if their decisions are bad than cede some power to software people. They are afraid that software people would become to powerful.
The ”game” of software development is rather ”won” by understanding the surrounding business and delivering on those goals rather than any, by software developers made up, “goals” about “standards”, “unit testing” or “SOLID design patterns”.
The game is also about good co-operation, helping colleagues succeed without imposing dogmatic requirements, and making friends with influential people connected to the software development team.
This is rather an article about loosing the “game”.
Dogmatic rules are for people that don’t know yet when to break the rules. Ironically, a lot of lead engineers I worked with don’t know that this is what dogmatic rules are for so they impose them to appear competent.
The author makes a list of things a “professional” developer uses. Among these are SOLID principles and design patterns. While they are good things to understand, I have met many developers who follow such principles without thinking and try to apply them to every task. This can make something really simple very complex when it doesn’t need to be.
I've had the misfortune of working at a few places were many/most of these things were pretty universally frowned upon.
> - Standards
Resistance to using formatters and linters because they prevent you from merging code more quickly; "it's annoying". Two of the two-dozen devs on the product decide that they want to use NetBeans instead of Eclipse even though the formatter is built for the the latter and everybody else uses it so they can't format their code properly.
> - Unit testing
I recently went four years without writing a single unit test professionally. When I _did_ write unit tests I worked on one team where the only important metric was coverage percentage, not corner/edge cases or intentionally trying to break the software. People would write tests for auto-generated getters and setters in C#. That's right - they would _test the compiler_ just to satisfy a business metric.
> - Design patterns/SOLID principles
My tech lead at a previous job refactored a pretty substantial service I wrote with no team input to remove any semblance of organization or convention. The repositories, factories, and facades I built got merged into a giant single "helper" object just to follow some weird anti-pattern that they'd established. It wasn't testable, there was no separation of concerns, and it ended up being nigh-unreadable.
> - Learning and setting DevOps and ALM (They like using it)
> - Fixing the build
I've been the "CI guy" at almost every software job I've had because some people are afraid of the command line and lack an understanding of the build tooling outside of the three SCM operations they know through Tortoise and the play button in their IDE.
I could go on but you get my point. Software development is a vast industry and there are some pretty dark corners. For every high-performing team that has tech-savvy devs there are body shops full of people that are trained by rote to "build software". It's not pretty.
In the game development, videogames are primarily tested by humans. Games are highly interactive pieces of software often running on a variety of hardware with complex agent-based simulations. Are all game developers "amateurs"? I don't think so.
Videogames overall are primary tested by humans, but smaller components inside them do have unit tests. Unit test and integration testing are two different things.
Nothing particularly unique about the software part. But the quoted text is interesting: that is kind of true about pro vs amateur tennis (or table tennis or badminton). Didn't quite notice it. Still, amateur tennis is funner when you play to win the point :D
158 comments
[ 6.6 ms ] story [ 237 ms ] thread>Why do I say this?
>Amateur software developers dislike
Is that a thing / the problem?
I appreciate that laundry list can contribute to writing good code, but I kinda wonder how much that has to do with it vs ... just not writing good code, for some other reason (time, bad incentives).
I've only been coding professionally for a handful of years, but I feel like I see a lot of reliance on various ideas and systems to produce good code. Programmers seem to think that they can enforce various systems and ideas to MAKE people write good code . While I think those can help, often I think those are used as all or nothing type measuring sticks.
Personally I think an individual programmer's choices are more (or maybe less) complex than that, as are the outcomes, regardless of some laundry list.
must live in ignorance, it seems easier to live :Ð
Many companies have very good processes in place and the above does not hold true for their employees. I was once at a company and was blown away with how well their code was structured, processes, etc I literally had no work to do (very rare).
Though I am a TDD fan I understand your point.
Yes and no. At $WORK we started using a security scanner and I'm triaging the issues. It's definitely a box ticking thing. OTOH I'm finding real, concerning issues.
Project I work at right now could really benefit from basic TDD principles, mainly just setting test / outcome matrices and basing production off of that (which logically follows into TDD). The requirements are largely set up front, yet we still shoehorn unit tests in after production is done, wasting both development and test time. Requirements rarely change in major ways, and they are often established months up front.
Other times I work on stuff where fundamentals change rapidly. At that point I'm spending 1.5x-2.5x the time just to include test I'm likely to remove, and TDD largely inflates time required I don't have or wish to spend. Often testing trivial things, too.
Most devs switch jobs in 2-5 years (or at least that's the common advice given). So the incentive is to play musical chairs, and hope that you've moved on by the time the music stops.
Software has also been such a new field that it was the startup that moved fast and broke things that got the prize rather than the slow but stable company. I think this is changing (lower barrier to entry and ever-increasing complexity). But the momentum still exists.
I chewed through tickets and regularly had an above average point score every sprint, even as a brand new junior developer. I sometimes had the highest on a team where everyone else had 5+ years of experience, which should have raised red flags. Heaps of praise though.
And I was doing it by taking the most direct path to it working without really knowing the potential consequences (which I didn't understand at the time).
The guy who wanted to do refactoring didn't get his contract renewed as that was not productive work.
I know because I did, multiple times. It’s futile. Your best move is to leave in that situation.
"Amaterur vs professional" feels "Good vs Bad" for me but real life is never as simple as that.
It's fascinating to see what people are doing with old hardware like Commodore 64, because it's understandable and doesn't change at this point. If we can use hardware that is almost 50 years old, why are cycling through things so rapidly?
Not their fault either, because maintaining old code is hard, frequently will introduce new bugs, and potentially halt business. Less hope for migrating into newer engine / language.
It's simply that software development is hard and we lack standardization more than any other industries.
But when those same devs go up the chain to improve practices or clean up tech debt, they rarely end up happy. I think that's because executive turnover is also fast and the rewards for underinvestment are much larger. Executive compensation is often tied to stock price and other short-term metrics, and executive tenure is also quite short. That gives them a strong incentive to cut anything that pays off over the long term.
Which I think ties back to his professionals vs amateurs thing. One thing that distinguishes professionals is standards. Doctors won't prescribe you anything you want. Real engineers will refuse to build things that will collapse. But a lot of devs are more minions than professionals; if the boss says to build X, they'll build X. Whether that's good for the company, the customers, or society isn't relevant.
"In order to release feature x which customer y cares about, we need to clear up tech debt / refactor z" is a much better way of getting execs on board.
But I think it's also worth orgs getting to the point of defaulting to just cleaning up after dinner, and also cleaning as they cook. Having to have a specific, urgent reason to clean up a mess is a fine argument for 13-year-olds to make as they come to understand how a household works. But it's tiresome when nominal adults refuse to accept that the future eventually arrives.
You can go all petty on minor idioms and force everyone to use all the sonar rules and all it will create is a lot of busywork with zero improvement on maintainability. And I have seen this dynamic to happen more then once.
I can think of a lot of successful professional teams who for the most part simply outlast their opponent by not making mistakes and capitalizing on their opponents mistakes.
American football for sure often has games turn on a handful of plays.
Looks like this is the Loser's Game essay he mentioned, btw. Also looks like in that essay, it's less about tennis and more about basically doing what the OP did, but applying the metaphor to investing: https://www.trendfollowing.com/whitepaper/the_losers_game.pd...
The hard part in all of these is finding the right "hooks" in these pursuits that tend to be more obvious in competitive games. How do you "record your performance" when programming or holding meetings about business strategy? How do you review that recording after the fact? What criteria do you use to evaluate success and failure?
It's certainly not as easy to do this with "games" that lack a clear scope like startups, but I've found regularly reviewing your performance ("Did this meeting have a clear agenda before starting?") and building checklists for what practices lead to success is immensely helpful.
Release crap that breaks too often? OK, you have taken too much of another team's resources, and will have to release less and/or check your work much more carefully.
Release something that might look low quality to an outsider, but that actually works perfectly well? Fine - no negative consequences if nothing bad happens.
Some years ago I've implemented a check to fail the PRs if the lines touched on that PR don't have code coverage (delta-coverage = 100%). We aligned internally with all the affected developers and went with it. We defined that the rule is that 100% of the code needs to be covered, but it doesn't mean that the rules can't have case-by-case exceptions. Whenever someone needs an exception the teams gets together and approve an exception. Sometimes it is a backlog to write the tests later, or some files that don't need unit tests altogether.
This may have worked for us because we are 5 years into this codebase and it keeps on growing, but for more small projects this may be more hassle than it is worth.
Honestly, after the first 6 months (not easy, not gonna lie) I felt better about the codebase, and I love the confidence of trying things and having unit tests all around. There were times where I submitted a PR and forgot altogether to write tests and this rule caught me.
I recommend it, but as with any software development practice, this is not a one-size-fits-all game.
I'd be more interested in project size, business pressure, cost incentives etc to explain why software always grow to a direction that seems to hinge on the unmanageable.
For instance I agree and implement all he says, but let's take one example: we can love unit tests, and I never push something for review without many, but there are fundamental limits to them: you can assert wrong in many ways without any kind of measure beyond coverage, you can make the same mistakes in the tests as you did in the implementation because you just misunderstood the business, you can rush a solution to solve a problem happening yesterday, and test half of the problem etc.
So doing unit tests ONLY won't save you either.
My 2 cent would be to make us users of the software, that would really help move towards stuff we stuffer tenfold the limitations and failures of. Adding unit test in the process is the absolute minimum (so I agree amateurs only should dislike them), but still just the minimum to get anything serious out. The maximum is to make us the clients, or them the programmers. A direction we discuss in investment banking where we fire traders to replace them with people who can launch profilers during automated trading.
"engaged in a specified activity as one's main paid occupation rather than as a pastime".
I wouldn't call fixing azure pipelines without any professional debugging tools a pastime activity.
Although I've met unprofessional people at work. Being a professional doesn't mean you're an expert.
Too many programmers read articles like this and assume that they are the 20% of good programmers while everyone who disagrees with them is the 80% of amateur developers:
> I have worked in software development for 20 years, worked on many projects with many software developers. I estimate 80 percent of software developers are amateurs and 20 percent professionals
Yes, it’s true that some programmers deliver better results than others. It’s also true that some have better methods than others. However, this is one of those situations where if you pulled developers aside and asked them to rank themselves relative to their peers, you might get 80% of people rating themselves as above average and 50% of people claiming to be in the top 20%.
A common pitfall I see is when developers forget that the goal is to ship software and instead focus on doing everything the most correct and perfect way they can think of, regardless of their resources. I’ve worked with many teams of professional programmers who spent so much time perfecting their tooling and code and architecture that they rarely ever shipped anything. Learning the tools of the trade is important, but don’t lose sight of the goal: We need to strike a balance and get work done, not just perfect our craft in a vacuum.
I mean, he's not wrong.. but I always get suspicious if somebody is making up percentages. You know 90% of percentages are made up? (Yes I just made that up)
It's a cheap, tiring tactic.
I get inconvenienced by other people's code all the time, but it's so easy to assume when you're looking at the bug "they should have known this was going to happen / tested for this" when you started your investigation knowing the trigger for the bug.
Anecdotal story: I had a bug a few weeks ago that all sorts of people thought was really dumb / obvious / shouldn't have happened. I checked... the code hadn't been changed for FIVE YEARS. Nearly every customer we had ran this code for five years. Maybe I feel that they should have had a catch for the situation that occurred, but whomever wrote it wrote code that lasted bug free for five years ... maybe they weren't dumb and they knew something I didn't?
Oh man that guy is the WORST.
When I was a junior dev I had a tendency to want to rewrite everything. I remember thinking that most the code I was working on at the time was overly complicated and could be done with far fewer lines of code. Recently I realised I might now be the guy that now overengineers and writes overly complicated code. I think this is common trend for devs too, as you mature you get really good at anticipating future problems so tend to write code that doesn't just meet the current requirements, but can scale into likely future requirements.
I feel like I've kind of gone full circle and now and I'm starting to question if there is a middle ground between the simplicity of writing simple code to solve a very specific problem and the extra time required in writing code that scales. The reason I say this is because I realised devs working on my code often don't fully understand the reasoning behind what I've written anyway and I and the devs working on my code often don't have the time to read / produce documentation explaining the code in detail. I also can't guarantee I'm always available to review PRs and ensure the code quality is maintained, so perhaps most of the time it's wasted effort.
Also often you just don't know what kind of constraints devs are working under. I know for a few projects with tight time constraints I've been asked to do the bare minimum to patch certain bugs or add some functionality so we can ship ASAP. I'll normally push back on this if I feel it's a bad idea, but code quality isn't always the most important consideration.
I realise I'm much more open minded when reading code now because after 15 years as a dev I'm still not sure I always do things right myself.
I've seen this. Huge big O complexity but on a dataset that fits in cache? Runs fine. As soon as the dataset gets bigger, you get systematic timeouts.
Of course most employers probably aren't looking for an "average" programmer, but I haven't found that they usually ask me to rank myself relative to others.
Programming is about doing the fundamentals well and consistently delivering
In many cases, companies just want you to sell yourself and hear the right things. Most companies know they can't hire a senior FAANG developer for $110k.
https://www.youtube.com/watch?v=t4A-Ml8YHyM
"It is possible to commit no mistakes and still lose. That is not a weakness. That is life."
There are so many of these, that they can become a culture majority and bring whole projects to a stop. When i encounter these, i tend to isolate them, link up with other reasonable people (who usually also work around them. If they have grown to powerful, you build two versions, one with their "architecture" (which they will inevitable grab and sink years of time into) and one that will be actually shipped, as a emergency solution.
If discussion is not possible, double the project estimate, cause there are two now.
I'm far, far more frustrated by developers who focus only on shipping software and making dates by cutting corners wherever they can and leave everybody else to deal with their gigantic mess later.
You don't need to cut corners to achieve cost effectiveness and tech debt is just that - debt, which always has to be paid eventually - either through expensive bugfixing, a rewrite or bad user experience.
The project's I've been in that went over budget usually had one or more of the following:
-Too large of a scope vs budget.
-Bad or no architecture whatsoever.
-Increasing personnel instead of reducing scope.
On the other hand projects with an architecture, a set of clear conventions and flexible scope fared much better.
Though I am not very keen on the underlying reasons the author gives. Seem to be anecdotal and not cover a host of other situations the solution could cover. I think there can be many other reasons. Cultural for one.
In the example of the professional team they may still be beholden to write cheap code because of certain business decisions, despite tests and the fanciest of ci builds. Additionally ‘amateur’ teams could still produce high functioning websites if there goals were shifted toward leaning and measurements taken against customer satisfaction and reduction of bugs over time.
This line is packaged to sound really insightful, but is it?
The goal of software development is to create software in support of some greater mission. That mission might be to make someone's life easier, to make money, to advance human knowledge, or many other things.
If I write no software today, I've also written no new bugs. But have I made any progress toward achieving the mission?
Feels like this person is very frustrated with novice engineers writing buggy code and has assumed a gatekeeper role to protect the integrity of the codebases in which he holds responsibility. It may be a necessary role at his organization, but I just don't agree with the cynical and depressing message.
Blaming all your issues on more junior members of the team is a huge red flag, and this article doesn't really offer any insight into how to bridge the gap between "amateur" and "professional" (which, imo, falls on the senior members of the team).
Senior members should set and enforce the standards via best practices, code reviews and setting the definition of done e.g. unit tests, data, deployable etc
Now maybe they did and the other person refuses to listen (not common in my experience), but I always wonder... you can't just make up 'rules' and expect folks to magically write good code because they followed a rule.
And although it took me a while to understand what the author is getting at, I do kind of see his point which in my mind could be summarized as: slow and steady wins the race. Or: In order to speed up (in the long run), slow down (in the short term). Be conservative, be thorough, understand that developer productivity isn’t about that LOC per x unit of time.
One analogy that comes to mind for me is Formula 1. Sure, it would be faster, right now, to just not pit. You would have to drive into the pit, stop and wait for the tyres to be changed and drive out again. Meanwhile your opponents are zooming past you out on the track. But if you don’t pit, soon enough your tyres will be worn down and it becomes impossible to keep heat and performance in them, and after a while longer you might even have to stop completely due to a puncture.
The ‘pitstop’ could be anything that ensures productivity in the long term and as such helps in reaching the final goal, and those are the things that take a professional to understand the importance of.
If that's the goal - the only goal - then all code is equal, and it doesn't matter how it's written. So... go crazy? Use global variables and goto statements? Hardcode path names and don't bother with build scripts? Writing software that works is challenging, but writing software that can be safely modified is even more so.
You gotta think long term (usually)
Practically the requirements are "have software that works, and will be sustainably developed and improved for 5 years". Making the trade offs in terms of "perfect code" to "good enough code" is what makes a software developer (in most settings) go from "good" to "great". Good software engineers can see all the edge cases and future paths. Great software engineers can prioritize those against business goals.
Just like "global variables and goto statements" is bad, so is "perfect, provably correct, and overtested" code in the vast majority of business settings.
Using his tennis analogy, each chunk of code written is like swinging at the tennis ball. You don't have to have the perfect curve-ball, you just have to NOT screw it up.
I've too often seen developers try to attack the ball with the perfect swing and the most force possible, only to have it go straight into the net. If they just focused on getting it over the net as simply as possible, the end result usually means less code that's easier to understand.
Example: junior dev needs to write a data transformation pipeline. They write a microservice and deploy it in Docker on Kubernetes. They do a lot of hand-wringing about reactive design and non-blocking I/O. They end up wrestling with the deploy and getting it done on time. All it needed to be was a simple single-threaded command line utility.
In 15 years, I've seen this story play out tons of times... I'm basically watching devs trip over themselves. I'm not saying I'm perfect either, this has happened to me too.
I completely agree with you.
You need to make something work before you can make it work well. You need to start simple before you dig into the complexity. Sometimes you find that the "stupid" solution is good enough.
I think it also takes experience to see that simple solutions can be more robust; the more natural response to foreseeing future problems (another trait) is to have specific responses for all of them, which generates a complex result.
At this point, I'm extremely unconvinced the problem is just education or juniority/seniority. The "paper factory" is just doing what companies are demanding. The real problem is a general lack of competence being used to market products, be they good when used properly (e.g. GoF, where many readers only look at design patterns and completely forget "composition over inheritance"), or snake oil.
I once had a boss who still coded, even though all the developers begged him to stop. His code was spaghetti, but worse was his inability to come up with more than one solution to a problem. If the first solution he came up with was complicated and error-prone then that's the one he proceeded with.
> You need to make something work before you can make it work well. You need to start simple before you dig into the complexity. Sometimes you find that the "stupid" solution is good enough.
100% true.
People love to dig at Test Driven Development, but it solves a common problem and is great for junior developers because it has 3 important rules.
1. Understand your requirements. And not in a wishy-washy hand-wavey way. But in an explicit, expressed as a single test verifiable/falsifiable requirement.
2. Implement the simplest solution that meets your requirements. Don't over-engineer anything, don't chase the latest fad, don't sleeve solve a way more complicated generic problem that you think we'll hit later, because you don't have enough experience to know how likely we are to hit it and the costs to make that tradeoff.
3. Keep you codebase clean and well factored. Don't let cruft and hacks build up.
Ignoring TDD, any junior engineer that can consistently exhibit those three behaviors is almost by no longer a junior engineer. Those are hard things to learn as an early coder.
Yes as you become mid-level and senior you should be more independent and break the above often - but at that point you have good foundations and the experience to make the tradeoffs to know when to deviate and by how much.
TDD is a very effective method for solving a problem that otherwise often takes a while to solve. Developing good fundamentals.
I feel obliged to mention that this very often goes against "do the stupidest thing that will work".
Most of the time in my career a clean codebase has naturally led to an intelligent solution which is definitely not the stupidest thing that will work.
Finally, it's also often the case that stupid code requires exorbitant amounts of comments or documentation, undermining the notion of it being simple to extend (which many conflate with the original premise). A little bit more intelligent code is usually self-describing.
I'm sure there's some range of nuance to your point, but it's also in line with the iterative philosophy isn't it? Do you find patching/revising things later to skew better/worse or some other downstream consequences?
It seems like you find that approach more efficient overall?
The whole point of design reviews, code reviews, senior devs, and more is to ensure that stuff that doesn’t work or can’t be maintained doesn’t get deployed.
That part (especially the second: maintenance) is endlessly contested in calls until some of us just give up and let the others reinvent the wheel for themselves because they don't listen to experience.
I think the article is saying we should focus on tooling that makes natural human errors less likely, instead of trying to focus on writing more code: in other words, write less code, ship it once without errors, instead of writing more code and having to go through the dev to prod feedback loop repeatedly. The tooling that helps you do that are DevOps practices, testing (and testability), simpler/more conservative design, and some time spent thinking about how to construct the software (or reconstruct it, when modifications are needed).
I wonder what his recruitment pipeline looks like where 80% of engineers end up not being productive.
Sounds like he's hiring wrong to begin with.
[1] https://tomgamon.com/posts/a-losers-game/
Both Ben in this "Software" and Tom Gamon in "Programming" anchor their arguments to Charles Ellis, & his example of tennis as a game where the talented score points, and amateurs inflict self harm.
Both of these articles espouse a similar, conservative minded viewpoint that maintaining & supporting is a more key or perhaps just more-absent activity than progressing. They warn that devotion to progressing/going out and winning often brings about doom & trouble. They speak to us of the hazards about, that the paths available to the software's future becomes confined or the ground unsteady if we don't take our software environment seriously.
I'm both very sympathetic to this software-conservatism , because (a) legacy systems/the past rule so much of the software world, and (b) we certainly do make confounded mistakes a lot, but also deeply worried about what it's done to our moral character. Software isn't eating the world anymore: it's past that now, that's past tense. Software has eaten the world. At almost everyone company you go to your world will almost entirely be already consumed by mounds of existing software, upon which the company is most often busy accreting new layers of software that will shortly settle into place & likewise become buried. It's a frank truth that minding your environment, trying to insure some safety & quality to the layers is critical, the belief that we should/ought/must build solid baseis extremely valuable here. But I somewhat fret programmers have been tamed into minding our own loser-dom, am concerned that we stop looking up to the stars, when we stop being brazenly brave. We have immense immense powers, and from so many camps- within the programmerhood & external- I see a reaction of panic, & fear, & distrust to potential. Which is both warranted, but also really quite besides the point, is too often too strong a diminishing force for great potentials programmers have such keen great sense for.
I feel there is an over-regulation, an over-pressuing on our social systems these days. "Overnight Pizza and the Consistent Unreliability of Expert Guidelines"[2][3] is recent article ostensibly about Expert Opinions & the low-information-density environments such guidelines are crafted in & for, but it's also an incredible story about social pressure, the urge to be right, about the emotional high one gets from being certainly completely correct & proper & everyone else being a fool. It's about overly absolutist perspectives, that don't allow for a bigger continuum of opinions. And I think a lot of software folk have turned in to the "overnight pizza will kill you" camp: they have encountered some parts of the maelstrom, tasted what the uncivilized is like, and their reaction is to build & fortify against the encroaching dark, to turtle up, & build strong best practices & robust processes. Which is both noble, respectable, given the maelstrom of software, but also... I feel like our lack of adventurous spirit often holds us to petty tasks, and keeps us from exploring & seeking better lands, with much richer yields.
[2] https://residentcontrarian.substack.com/p/overnight-pizza-an...
[3] https://news.ycombinator.com/item?id=26635856
Programmers,...
> Software engineering has its own political axis, ranging from conservative to liberal.
Which is really very much at the heart of what this whole winners vs losers game discussion is about, I think.
[1] https://gist.github.com/cornchz/3313150
>Only rarely does the business let us drive towards the true fantastic excellences that we dream of pursuing. Just as the business doesn't understand the loser's game challenges that are all over the place, oh, sad, the business also does not have anywhere near the vision or creativity of the individual, of the coder, who sees possibility & value oozing out of so many areas, often so untapped. And programmers are not put into decision making roles nearly enough, not given structure & the attitude that they can strike, that they can chase down big game, game the rest of the company often has a hard time seeing. The socialization processes that work places must go through to allow commitment are very high, and so programmers simply do not have the time, ability, or often even the common language to get the businesses play the winning game. We must trust that the business somehow is aligned to let us make them kings, rather than taking an active stake in pushing the business towards their would be kingdomship.
The socializing aspect is spot on but there is also a fear that the business people have of losing control. On the software domain they are clueless and they prefer to keep the reigns, even if their decisions are bad than cede some power to software people. They are afraid that software people would become to powerful.
The game is also about good co-operation, helping colleagues succeed without imposing dogmatic requirements, and making friends with influential people connected to the software development team.
This is rather an article about loosing the “game”.
>Amateur software developers dislike
- Standards
- Unit testing
- Design patterns/SOLID principles
- Learning and setting DevOps and ALM (They like using it)
- Fixing the build
- Code reviews
- Code Analysis/Solution checking
What a troll statement, no way do 80% of software developers dislike those things.. maybe.. 20%?
> - Standards
Resistance to using formatters and linters because they prevent you from merging code more quickly; "it's annoying". Two of the two-dozen devs on the product decide that they want to use NetBeans instead of Eclipse even though the formatter is built for the the latter and everybody else uses it so they can't format their code properly.
> - Unit testing
I recently went four years without writing a single unit test professionally. When I _did_ write unit tests I worked on one team where the only important metric was coverage percentage, not corner/edge cases or intentionally trying to break the software. People would write tests for auto-generated getters and setters in C#. That's right - they would _test the compiler_ just to satisfy a business metric.
> - Design patterns/SOLID principles
My tech lead at a previous job refactored a pretty substantial service I wrote with no team input to remove any semblance of organization or convention. The repositories, factories, and facades I built got merged into a giant single "helper" object just to follow some weird anti-pattern that they'd established. It wasn't testable, there was no separation of concerns, and it ended up being nigh-unreadable.
> - Learning and setting DevOps and ALM (They like using it)
> - Fixing the build
I've been the "CI guy" at almost every software job I've had because some people are afraid of the command line and lack an understanding of the build tooling outside of the three SCM operations they know through Tortoise and the play button in their IDE.
I could go on but you get my point. Software development is a vast industry and there are some pretty dark corners. For every high-performing team that has tech-savvy devs there are body shops full of people that are trained by rote to "build software". It's not pretty.
In the game development, videogames are primarily tested by humans. Games are highly interactive pieces of software often running on a variety of hardware with complex agent-based simulations. Are all game developers "amateurs"? I don't think so.
Any idea on how they get the kernel to scale without kubernetes?