17 ms·
Do the simplest thing that could possibly work
- baronswindle 1y agoIn my experience, simplicity can be a bit of a slippery concept. Often, people use the word “simple” to mean “intuitive to me”.
- dondraper36 1y agoThat's exactly the "simple vs easy" difference that Rich Hickey emphasized in his famous talk.
- deleted 1y ago[deleted]
- al_borland 1y ago“Everything should be made as simple as possible, but not simpler.” As someone who has strived for this from early on, the problem the article overlooks is not knowing some of these various technologies everyone is talking about out, because I never felt I needed them. Am I missing something I need, but just ignorant, or is that just needless complexity that a lot of people fall for? I don’t want to test these things out to learn them in actual projects, as I’d be adding needless complexity to systems for my own selfish ends of learning these things. I worked with someone who did this and it was a nightmare. However, without a real project, I find it’s hard to really learn something well and find the sharp edges.
- IAmBroom 1y agoYes, and I (nearly) live this nightmare. I have someone higher up in the food chain who is fascinated with every new piece of software they find, that MIGHT be useful. We are often tasked with "looking at it, and seeing if it would be useful". Yeah, let me shoehorn that fishing trip into my schedule without a charge number, along with the one from last week...
- colecut 1y agoDoes he ask you to "figure out how to implement AI"? That is what my boss asks us to do =p
- IAmBroom 1y agoNo, fortunately as an engineering firm (construction), we have strong corporate guidelines on usage of that Pandora's Box.
- deleted 1y ago[deleted]
- al_borland 1y agoI was the go-to guy for this under my former boss, but he let me do pretty much whatever I wanted, so it usually wasn’t an issue to not work on anything else while playing around with new stuff. Though there was a time when he wanted me to onboard my simple little internal website to a big complicated CICD system, just so we could see how it worked and if it would be useful for other stuff. It wouldn’t have been useful for anything else, and I already had a script that would deploy updates to my site that was simple, fast, and reliable. I simply ignored every request to look into that. Other times I could tell him his idea wouldn’t work, and he would say “ok” and walk away. That was that. This accounted for about 30% of what he came to me with.
- threemux 1y agoThis is indeed a vexing issue. I feel it often. It's this feeling that leads to resume-driven development which I really work hard to avoid.
- dondraper36 1y agoSuch a familiar feeling. Articles similar to this one make lots of sense to and I do try to embrace simplicity and not optimize prematurely, but very often I have no idea whether it's the praised simplicity and pragmatism or just a lack of experience and skills.
- SPascareli13 1y agoImplement the simplest thing that works, maybe even by hand at first, instead of adding the tool that does "the whole thing" when you don't need "the whole thing". Eventually you might start adding more things to it because of needs you haven't anticipated, do it. If you find yourself building the tool that does "the whole thing" but worse, then now you know that you could actually use the tool that does "the whole thing". Did you waste time not using the tool right from the start? That's almost a filosofical question, now you know what you need, you had the chance to avoid it if it turned out you didn't, and maybe 9 times out of 10 you will be right.
- mrkeen 1y ago> Am I missing something I need, but just ignorant, or is that just needless complexity that a lot of people fall for? Ignorance plays a big role. If you don't perceive, e.g. a race condition happening, then it's much simpler to avoid complicated things like locking and synchronisation. If you have the belief that your code will never be modified after you commit it, then it's much simpler to not write modifiable code. If you believe there's no chance of failure, then it's simpler to not catch or think about exceptions. The simplest thing is global variables, single-letter variable names, string-handling without consideration for escaping, etc.
- al_borland 1y agoFor the basics inside a single code base, like error handling, maintainability, race conditions, etc, I’m thinking about most of that. It’s more about adding additional tools to the stack. I will fight hard not to add in additional layers of complexity that require more infrastructure and maintenance to manage. I want to eliminate as many points of failure as possible, and don’t want the stack to be so complex that other people can’t understand how it all fits together. If I win the lotto, or simply go on vacation, I want whoever has to take it over to be able to understand and support it. The thing I’ll be working on next week has a lot of potential race conditions, and I need to find a simple solution that avoid them, without creating a support and maintainability burden on myself and the future team. Building a database would probably be the easy solution, but that’s one more dependency and thing to maintain, and also means I need to build a front end for people to access it. If I can do it without a database, that would be ideal.
- hinkley 1y agoOne of the biggest, evergreen arguments I’ve had in my career revolves around the definition of “works”. “Just because it works doesn’t mean it isn’t broken.” Is an aphorism that seems to click for people who are also handy in the physical world but many software developers think doesn’t sound right. Every handyman has at some time used a busted tool to make a repair. They know they should get a new one, and many will make an excuse to do so at the next opportunity (hardware store trip, or sale). Maybe 8 out of ten. In software it’s probably more like 1 out of ten who will do the equivalent effort.
- mandelbrotwurst 1y agoThose conversations are an important part of the job. You can, for example, agree that something works in the sense that it is currently possible to use it to obtain a desired output, while simultaneously failing to work in various ways: It might fail to do so reliably, or it might only be able to do so at great cost.
- hinkley 1y agoIt’s a frustrating argument to lose. On a recent project I fixed our deployment and our hotfix process and it fundamentally changed the scope of epics the team would tackle. Up to that point we were violating the first principle of Continuous: if it’s painful, do it until it isn’t. So we would barely deploy more often than we were contractually (both in the legal and internal cultural sense) obligated to do, and that meant people were very conservative about refactoring code that could lead to regressions, because the turnaround time on a failing feature toggle was a fixed tempo. You could turn a toggle on to analyze the impact but then you had to wait until the next deployment to test your fixes. Excruciating with a high deviation for estimates. With a hotfix process that actually worked worked, people would make two or three times as many iterations, to the point we had to start coordinating to keep people from tripping over each other. And as a consequence old nasty tech debt was being fixed in every epic instead of once a year. It was a profound change. And as is often the case, as the author I saw more benefit than most. I scooped a two year two man effort to improve response time by myself in three months, making a raft of small changes instead of a giant architectural shift. About twenty percent of the things I tried got backed out because they didn’t improve speed and didn’t make the code cleaner either. I could do that because the tooling wasn’t broken.
- ashwinsundar 1y agoA related concept: https://en.wikipedia.org/wiki/Poka-yoke https://en.wikipedia.org/wiki/Poka-yoke
- hu3 1y agoAlso: https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it You aren't gonna need it
- hiAndrewQuinn 1y agoOn the meta level, the simplest thing that could possibly work is usually paying someone else to do it. Alas, you do not have infinite money. But you can earn money by becoming this person for other people. The catch 22 is most people aren't going to hire the guy who bills himself as the guy who does the simplest thing that could possibly work. It turns out the complexities actually are often there for good reason. It's much more valuable to pay someone who has the ability to trade simplicity off for other desirable things.
- switchbak 1y agoIf I was running a business and I could hire someone that I knew did good work, and did the simplest thing that could possibly work (and it actually worked!) - then I would absolutely do that as soon as possible. "It turns out the complexities actually are often there for good reason" - if they're necessary, then it gets folded into the "could possibly work" part. The vast majority of complexities I've seen in my career did not have to be there. But then you run into Chesterton's Fence - if you're going to remove something you think is unnecessary complexity, you better be damn sure you're right. The real question is how AI tooling is going to change this. Will the AI be smart enough to realize the unnecessary bits, or are you just going to layer increasingly more levels of crap on top? My bet is it's mostly the latter, for quite a long time.
- ChefboyOG 1y ago"Will the AI be smart enough to realize the unnecessary bits, or are you just going to layer increasingly more levels of crap on top? My bet is it's mostly the latter, for quite a long time." Dev cycles will feel no different to anyone working on a legacy product, in that case.
- oncallthrow 1y agoThis just kicks the can down the road. What is "simple"? What does "works" mean?
- dondraper36 1y agoI don't think the author (or anyone else) could come up with term definitions that would satisfy everyone.
- dondraper36 1y ago... and nevertheless at the end of the article, the author does offer their understanding of the terms
- bearjaws 1y agoYou know what taught me this the best? Watching Mythbusters. Time and time again amazingly complex machines and they just fail to perform better than a rubber-band and bubble gum.
- lstodd 1y agoeh.. there were series of clips named something like 'Industrial JP' showing the multiaxis (like 6 to 12 axis) spring coil forming machines working This stuff just can not be reimplemented that simple and be expected to work. The music was also quite good imo.
- underdeserver 1y agoGreat advice. I always felt software is like physics: Given a problem domain, you should use the simplest model of your domain that meets your requirements. As in physics, your model will be wrong, but it should be useful. The smaller it is (in terms of information), the easier it is to expand if and when you need it.
- daxfohl 1y ago"It’s fun to decouple your service into two pieces so they can be scaled independently (I have seen this happen maybe ten times, and I have seen them actually be usefully scaled independently maybe once)." Same, or reliability-tiered separately. But in both aspects I more frequently see the resulting system to be more expensive and less reliable.
- gonational 1y agoDealing with this exact scenario, right now. My company has implemented an unnecessarily complex spiderweb of services and the litany of problems that go along with it, in anticipation of some hypothetical, future requirements. Most of the team is fairly new, but they have been led astray by a mid-level engineer who has been masquerading as a top level engineer. By the time I came along, the damage was already done, and the rest of the team is unaware that they have developed about 60 days worth of software, mostly code debt, in more than 18 months. The situation is extremely frustrating, because I have to be careful not to insult anyone or create endless arguments, while trying to somehow salvage the project into something workable, or convince a team of junior/mid-level engineers to start over (the code is technically not salvageable, at all). Trying to convince people who don't know what they're doing that the same end result could be reproduced in 45 days and then the next 18 months of effort could be condensed into an additional 45 days is like trying to convince an octopus that there are satellites in orbit around the Earth.
- bifftastic 1y agoSee also https://wiki.c2.com/?DoTheSimplestThingThatCouldPossiblyWork https://wiki.c2.com/?DoTheSimplestThingThatCouldPossiblyWork
- kristianp 1y ago> when I asked [KentBeck], "What's the simplest thing that could possibly work?" I wasn't even sure. I wasn't asking, "What do you know would work?" I was asking, "What's possible? What is the simplest thing we could say in code, so that we'll be talking about something that's on the screen, instead of something that's ill-formed in our mind?" I was saying, "Once we get something on the screen, we can look at it. If it needs to be more, we can make it more.
- deleted 1y ago[deleted]
- ChrisMarshallNY 1y agoOckham's Software Architecture...
- deepsun 1y agoDon't bother with SSL, it's adds complexity. Don't add passwords, just "password" is fine. Password policies add complexity. For services that require passwords just create a shared spreadsheet for everyone. /s
- dondraper36 1y agoIsn't reading the article before posting comments considered cool anymore?
- GMoromisato 1y agoOne of the ironies of this kind of advice is that it's best for people who already have a lot of experience and have the judgement to apply it. For instance, how do you know what the "simplest thing" is? And how can you be sure that it "could possibly work"? Yesterday I had a problem with my XLSX importer (which I wrote myself--don't ask why). It turned out that I had neglected to handle XML namespaces properly because Excel always exported files with a default namespace. Then I got a file that added a namespace to all elements and my importer instantly broke. For example, Excel always outputs <cell ...> whereas this file has <x:cell ...>. The "simplest thing that could possibly work" was to remove the namespace prefix and just assume that we don't have conflicting names. But I didn't feel right about doing that. Yes, it probably would have worked fine, but I worried that I was leaving a landmine for future me. So instead I spent 4 hours re-writing all the parsing code to handle namespaces correctly. Whether or not you agree with my choice here, my point is that doing "the simplest thing that could possible work" is not that easy. But it does get easier the more experience you have. Of course, by then, you probably don't need this advice.
- bvirb 1y agoWe attempt to address this problem at work with an extra caveat to never add code "in the wrong direction" -- so it's fine (usually preferable) to have a partial implementation, as long as it's heading in the direction we'd like the more complete implementation to go in. Basically "KISS, but no hacks".
- GMoromisato 1y agoI really like this as a guideline.
- ehansdais 1y agoJust curious, how would that be applied to the xslx namespace problem example given? If the full fix is to implement namespacing, what would the KISS approach be in the right direction?
- jiggawatts 1y ago
- ternaryoperator 1y agoIt's a shame he doesn't give the origin of this expression in programming. It comes from Ward Cunningham (inventor of the wiki) in his work with Kent Beck. In an interview a few years back on Dr. Dobb's, he stated that as the two of them were coding together in the late 80s, they would regularly remind each other of the principle. Eventually, it became a staple of their talks and writing. They were cognizant of the limitations that are touched on in this article. The example they gave was of coming to a closed door. The simplest thing might be to turn the handle. But if the door is locked, then the simplest thing might be to find the key. But if you know the key is lost, the simplest thing might be to break down the door, and so on. Finding the simplest thing is not always simple, as the article states IIRC, they were aware that this approach would leave a patchwork of technical debt (a term coined by Cunningham), but the priority on getting code working overrode that concern at least in the short term. This article would have done well to at least touch on the technical debt aspect, IMHO.
- jdlshore 1y agoKent Beck went on to formalize Extreme Programming, which is a collection of practices for allowing simple systems to evolve as requirements change.
- evanmoran 1y agoHere’s the Extreme Programming manifesto from that time. Very similar sentiment from around two decades ago. http://www.extremeprogramming.org/rules/simple.html http://www.extremeprogramming.org/rules/simple.html
- commandersaki 1y agoYet its maiden project was an abject failure.
- thefourthchime 1y agoThis should be the top comment.
- socalgal2 1y ago
- daxfohl 1y agoI wholeheartedly agree with this. The challenge is perception though. Many managers will see a simple solution to a complex problem and dock you for not doing real engineering, whereas a huge convoluted mess to solve a simple problem (or non-problem) gets you promoted. And in design interviews, "I'd probably implement a counter in memory" would be the last time you ever heard from that company.
- deleted 1y ago[deleted]
- JackFr 1y agoBefore you write a parser, try a regex. (But some times you really do need a parser.)
- dochtman 1y agoI would argue that regexes are often more complex than simple parsers.
- dondraper36 1y agoThat's where the familiarity factor steps in.
- sfpotter 1y agoGenerally speaking, when I hear people say this, it's a huge red flag. Really, any time anyone puts forth any kind of broad proclamation about how software development should be done, my hackles go up. Either they don't know what they're talking about, they're full of shit, or both. The only reasonable thing to conclude after lots of experience with software development is that it's hard and requires care and deliberation. There is no one-size-fits-all advice. What I want to see is people who are open-minded and thoughtful.
- switchbak 1y agoI mean, I think I agree more with this sentiment than most. These overly general statements tend to not have much nuance, and do little to incorporate context. But also keep in mind the audience: the kinds of people who are tempted to use J2EE (at the time) with event sourcing and Semantic Web, etc. This is really a counterbalance to that: let's not add sophistication and complexity by default. We really are better off when we bias towards the simpler solutions vs one that's overly complex. It's like what Dan McKinley was talking about with "Choose Boring Technology". And of course that's true (by and large), but many in our industry act like the opposite is the case - that you get rewarded for flexing how novel you can make something. I've spent much of my career unwinding the bad ideas of overly clever devs. Sometimes that clever dev was me! So yes ... it's an overly general statement that shouldn't need to be said, and yet it's still useful given the tendency of many to over-engineer and use unnecessarily sophisticated approaches when simpler ones would suffice.
- whizzter 1y agoI was initially annoyed at parts of the article, but it does point out that "hacks" often adds hidden complexity that isn't simple so there is a clarity about the tradeoff. Now the problem with the headline and repeating it is, when "just do a simple thing" becomes mandated from management (technical or not), there comes a certain stress about trying to keep it simple and if you try running with it for a complex problems you easily end up with those hacks that become innate knowledge that's hard to transfer instead of a good design (that seemed complex upfront). Conversly, I think a lot of "needless complexity" comes from badly planned projects where people being bitten by having to continuously add hacks to handle wild requirements easily end up overdesigning something to catch them, only to end up with no more complexity in that area and then playing catchup with the next area needing ugly hacks (to then try to design that area that stabilized and the cycle repeats). This is why as developers we do need to inject ourselves into meetings (however boring they are) where things that do land up on our desks are decided.
- 0xbadcafebee 1y agoHard, hard disagree. First of all, simplicity is the hardest thing there is. You have to first make something complex, and then strip away everything that isn't necessary. You won't even know how to do that properly until you've designed the thing multiple times and found all the flaws and things you actually need. Second, you will often have wildly different contexts. - Is this thing controlling nuclear reactors? Okay, so safety is paramount. That means it can be complex, even inefficient, as long as it's safe. It doesn't need to be simple. It would be great if it was, but it's not really necessary. - Is the thing just a script to loop over some input and send an alert for a non-production thing? Then it doesn't really matter how you do it, just get it done and move on to the next thing. - Is this a product for customers intended to solve a problem for them, and there's multiple competitors in the space, and they're all kind of bad? Okay, so simplicity might actually be a competitive advantage. Third, "the simplest thing that could possibly work" leaves a lot of money on the table. Want to make a TV show that is "the simplest thing that could possibly work"? Get an iPhone and record 3 people in an empty room saying lines. Publish a new episode every week. That is technically a TV show - but it would probably not get many views. Critics saying that you have "the simplest show" is probably not gonna put money in your pocket. You want a grand design principle that always applies? Here's one: "Design for what you need in the near future, get it done on time and under budget, and also if you have the time, try to make it work well."
- zahlman 1y ago> First of all, simplicity is the hardest thing there is. You have to first make something complex, and then strip away everything that isn't necessary. I don't follow. I've made simple things many times without having to make a complex thing first.
- 0xbadcafebee 1y agoThat would make you a genius, so congrats :-) It's more likely that you thought it was simple, but it actually wasn't. Was it actually the least-complex thing that works? Or was it just a thing that worked, and it didn't seem complex? Because those are two different things.
- 1y ago
- codingwagie 1y agoI think this works in simple domains. After working in big tech for a while, I am still shocked by the required complexity. Even the simplest business problem may take a year to solve, and constantly break due to the astounding number of edge cases and scale. Anyone proclaiming simplicity just hasnt worked at scale. Even rewrites that have a decade old code base to be inspired from, often fail due to the sheer amount of things to consider. A classic, Chesterton's Fence: "There exists in such a case a certain institution or law; let us say, for the sake of simplicity, a fence or gate erected across a road. The more modern type of reformer goes gaily up to it and says, “I don’t see the use of this; let us clear it away.” To which the more intelligent type of reformer will do well to answer: “If you don’t see the use of it, I certainly won’t let you clear it away. Go away and think. Then, when you can come back and tell me that you do see the use of it, I may allow you to destroy it.”"
- jaynate 1y agoWow, Chesterton’s fence parable could apply in so many places (not the least of which, politics).
- dondraper36 1y agoThe author is a staff engineer at GitHub. I don't think they haven't worked at scale
- deleted 1y ago[deleted]
- pinoy420 1y ago[flagged]
- rednafi 1y agoMan, who hurt you? I certainly don’t agree with everything Sean says and admit that “picking the most important work” is a naive thing to say in most scenarios. But writing Python in production is trivial. Why would anyone lie about that? C is different OTOH. But just because you do a single config change and get paid for that doesn’t mean it’s true for everyone. Also, staff at GitHub requires a certain bar of excellence. So I wouldn’t blindly dismiss everything just out of spite.
- jumploops 1y agoAs someone who has built 0-1 systems at multiple startups (Seed to Series C), I’ve settled on one principle above all else: “Simple is robust” It’s easy to over-design a system up front, and even easier to over-design improvements to said system. Customer requirements are continually evolving, and you can never really predict what the future requirements will be (even if it feels like you can). Breaking down the principle, it’s not just that a simple system is less error prone, it’s just as important that a simple architecture is easier to change in the future. Should you plan for X, Y, and Z? Yes, but counterintuitively, by keeping doors open for future and building “the simplest thing that could possibly work.” Complexity adds constraints, these limitations make the stack more brittle over time, even when planned with the best intentions.
- mindcrime 1y agoIMO, the most important thing about this sort of advice (and maybe most advice) is to treat it as a "generally useful heuristic, subject to refinement based on judgment" and not as an "ironclad, immutable law of the kingdom, any transgression from which, will be severely punished". Sure, try to keep things simple. Unless it doesn't make sense. Then make them less simple. Will you get it wrong sometimes? Yes. Does it matter? Not really. You'll be wrong sometimes no matter what you do, unless you are, in fact, the Flying Spaghetti Monster. You're not, so just accept some failures from time to time and - most importantly - reflect on them, try to learn from them, and expect to be better next time.
- dondraper36 1y agoUntil you get enough experience for your own good judgment, you need some rules of thumb and guidelines from more experienced peers. As long as you understand that everything is a trade-off and, unfortunately, that the modern field is based on subjective opinions of popular and not necessarily competent people, you will be fine.
- bvirb 1y agoVery much agree for the type of software I've worked on my whole career. I've seen way more time and energy wasted by people trying to predict the future than fixing bugs. In practice I think it's common to realize something didn't "possibly work" until after it's already deployed, but keeping things simple makes it easy to fix. So this advice also ends up basically being "move fast break things".
- spectraldrift 1y agoI agree with the spirit of the article, but I think the definition of "simple" has been inverted by modern cloud infrastructure. The examples create a false choice between a "simple but unscalable" system and a "complex but scalable" one. That is rarely the trade-off today. The in-memory rate-limiting example is a perfect case study. An in-memory solution is only simple for a single server. The moment you scale to two, the logic breaks and your effective rate limit becomes N × limit. You've accidentally created a distributed state problem, which is a much harder issue to solve. That isn't simple. Compare that to using a managed service like DynamoDB or ElastiCache. It provides a single source of truth that works correctly for one node or a thousand. By the author's own definition that "simple systems are stable" and require less ongoing work, the managed service is the fundamentally simpler choice. It eliminates problems like data loss on restart and the need to reason about distributed state. Perhaps the definition of "the simplest thing" has just evolved. In 2025, it's often not about avoiding external dependencies. You will often save time by leveraging battle-tested managed services that handle complexity and scale on your behalf.
- dasil003 1y agoI don't think this is particular to cloud infrastructure. Even on a single server you could make the same argument about using flat file vs sqlite vs postgres for storage. Yes, there is a lot of powerful and reusable software, both managed and unmanaged, with good abstractions and great power to weight ratios where you pay a very small complexity cost for an incredible amount of capability. Such is the nature of software. But all of it comes with tradeoffs and you have to apply judgement. Just as it would be foolish to write almost anything these days in assembly, I think it would be almost as foolish to just default to a managed Amazon service because it scales without considering whether A) you actually need that scale and B) there are other concerns considerations as to why that service might not be the best technical fit (in particular, I've heard regrets due to overzealous adoption of DynamoDB on more than one occasion).
- spectraldrift 1y agoYou make a good point about experience. I've noticed an interesting paradox there. The engineers who most aggressively advocate for bespoke solutions in the name of "simplicity" often have the least experience with their managed equivalents, which can lead to the regrets you mentioned. Conversely, many engineers who only know how to use managed services would struggle to build the simple, self-contained solution the author describes. True judgment requires experience with both worlds. This is also why I think asking "do we actually need this scale?" is often the wrong question; it requires predicting the future. Since most solutions work at a small scale, a better framework for making a trade-off is: * Scalability: Will this work at a higher scale if we need it to? * Operations: What is the on-call and maintenance load? * Implementation: How much new code and configuration is needed? For these questions, managed services frequently have a clear advantage. The main caveat is cost-at-scale, but that’s a moot point in the context of the article's argument.
- axblount 1y ago"When in doubt, use brute force." --Ken Thompson
- bwy 1y agoFrom https://nshipster.com/uncertainty/ https://nshipster.com/uncertainty/ recently: "Working in software, the most annoying part of reaching Senior level is having to say “it depends” all the time. Much more fun getting to say “let’s ship it and iterate” as Staff or “that won’t scale” as a Principal." IIUC, author is a Staff SWE, so this tracks. See also "Worse is better" which has been debated a million times by now.
- evo 1y agoAnother way I like to think about this is finding 'closeable' contexts to work in; that is, abstractions that are compact and logically consistent enough that you can close them out and take them on their external interface without always knowing the inner details. Metaphorically, your system can be a bunch of closed boxes that you can then treat as boxes, rather than a bunch of open boxes whose contents are spilling out and into each other. Think 'shipping containers' instead of longshoremen throwing loose cargo into your boat. If you can do this regularly, you can keep the _effective_ cognitive size of the system small even as each closed box might be quite complex internally.
- spelunker 1y agoThis is also good advice for personal projects - want to ship stuff? Just do what works, nobody cares!
- ineedasername 1y agoA few notes: 1) Sometimes the simplest things is still extremely complex 2) The simplest thing that works is often very hard to find
- kiitos 1y agousing unicorn as a positive example is, well, a pretty negative signal unicorn, i.e. CGI, i.e. process-per-request, became anachronistic, gosh, more than 20 years ago at this point! at least, if you're serving any kind of meaningful load -- a bash script in a while loop can serve 100RPS on an ec2.micro, that's (hopefully) not what anyone is talking about
- BenoitEssiambre 1y agoThis is good advice but it can be difficult to define what simple means. The only technical way I was able to make sense of it is by targeting reducing code entropy and scopes (Inspired by how language models try to minimize Solomonoff/Kolmogorov entropy). https://benoitessiambre.com/entropy.html https://benoitessiambre.com/entropy.html https://benoitessiambre.com/integration.html https://benoitessiambre.com/integration.html
- wtbdbrrr 1y agowonderful piece. applies to the narrative 'unfuck' anything as well. any industry and any 'behavioral lock in' and so on.
- uberduper 1y agoI wanted to like this article and there's some things in there to agree with but ultimately it's a very uninteresting take with a very unconvincing rate limiting example. > System design requires competence with a lot of different tools: app servers, proxies, databases, caches, queues, and so on. Yes! This is where I see so many systems go wrong. Complex software engineering paving over a lack of understanding of the underlying components. > As they gain familiarity with these tools, junior engineers naturally want to use them. Hell yea! Understanding how kafka works so you don't build some crazy queue semantics on it. Understanding the difference between headless and clusterIP services in kubernetes so you don't have to build a software solution to the etcd problems you're having. > However, as with many skills, real mastery often involves learning when to do less, not more. The fight between an ambitious novice and an old master is a well-worn cliche in martial arts movies Wait what? Surely you mean doing more by writing less code. Are you now saying that learning and using these well tested, well maintained, and well understood components is amateurish?
- hyperpape 1y ago> You should do that too! Suppose you’ve got a Golang application that you want to add some kind of rate limiting to...Actually, are you sure your edge proxy doesn’t support rate limiting already? Could you just write a couple of lines in a config file instead of implementing the feature at all? As I'm doing the simplest thing that could possibly work, I do not have an edge proxy. Of course, the author doesn't mean _that_ kind of simplicity. There are always hidden assumptions about which pieces of complexity are assumed, and don't count against your complexity budget.
- jiggawatts 1y agoThis is the advice I've been unsuccessfully trying to drill into the heads of developers at a large organisation. Unfortunately, it turns out that the "simplest thing" can be banged out in a couple of days -- mere hours with an AI -- and that just isn't compatible with a career that is made up of 6-month contracting stints. It's much, much more lucrative to drag out every project over years and keep collecting that day-rate. Many "industry best-practices" seen in this light are make-work, a technique for expanding simple things to fill the time to keep oneself employed. For example, the current practice of dependency injection with interfaces, services, factories, and related indirections[1] is a wonderful time waster because it can be so easily defended. "WHAT IF we need to switch from MySQL to Oracle DB one day?" Sure, that... could happen! It won't, but it could. [1] No! You haven't created an abstraction! You've just done the same thing, but indirectly. You've created a proxy, not a pattern. A waste of your own time and the CPU's time.
- AlotOfReading 1y agoIt's a pithy philosophy if you already know what it means to "work". You probably don't, especially if your system is human facing. Figuring out what "works" means is almost as difficult as building things in the first place. You may as well commit to building it twice [0]. [0] https://ratfactor.com/cards/build-it-twice https://ratfactor.com/cards/build-it-twice
- logsr 1y ago> design the best system for what your requirements actually look like right now this is the key practical advice. when you start designing for hypothetical use cases that may never happen you are opening up an infinite scope of design complexity. setting hard specifications for what you actually need and building that simplifies the design process, at least, and if you start with that kind of mindset one can hope that it carries over to the implementation. the simplest things always win because simple is repeatable. not every simple thing wins (many are not useful or have defects) but the winners are always simple.
- amelius 1y ago> > design the best system for what your requirements actually look like right now But don't forget to ask your manager if they want to be prepared for future scenarios A, B, or C. And write down their answer for later reference.
- RajT88 1y agoI appreciate the sentiment, and absolutely think it should be kept in mind more. But of course, it runs afoul of reality a lot of the time. I recently got annoyed that the Windows Task scheduler just sometimes... Doesn't fucking work. Tasks don't run, and you get a crazy mystery error code. Never seen anything like it. Drives me nuts. Goddamned Microsoft making broken shit! I mostly write Powershell scripts for automating my system, so I figure I'll make a task scheduler which uses the C# PSHost to run the scripts, and keep the task configuration in a SQLite database. Use a simple tray app with a windows form and EFCore for SQLite to read and write the task configuration. Didn't take too long, works great. I am again happy, and even get better logging out of failure conditions, since I can trap the whole error stream instead of an exit code. My wife is starting a business, and I start to think about using the business to also have a software business piece to it. Maybe use the task scheduler as a component in a larger suite of remote management stuff for my wife's business which we sell to similar businesses. Well. For it to be ready, it's got to be reliable and secure. Have to implement some checks to wait if the database is locked, no biggie. Oh, but what happens if another user running the tray icon somehow can lock the database, I've got to work out how to notify the other user that the database is locked... Also now tasks need to support running as a different user than the service is running under. Now I have to store those credentials somewhere, because they can't go into the SQLite DB. DPAPI stores keys in the user profile, so all this means now I have to implement support for alternative users in the installer (and do so securely, again with the DPAPI, storing the service's credentials). I've just added a lot of complexity to what should be a pretty simple application, and with it some failure modes. Paying customers want new features, which add more complexity and more concern cases. This is normal software entropy, and to some extent it's unavoidable.
- bleepblap 1y agoHad to make an account for this, but this is almost verbatim what the article is talking about: Your wife is making a business, and you want to write some code to help. Then suddenly your requirements balloon to multiple concurrent users, needing to have a system tray icon and then also the ability to take this code and sell it to other people. Wow this project is suddenly complex! This is just "I need to be able to scale infinitely" written in different words. The complexity comes from wanting a ton of things before they're actually needed (with the wrinkle of wanting to use some previously written scheduler for this project.
- screye 1y agoIt's great advice for an individual or a work item. It's great advice for teams where untamed programmers run rampant. It's good advice when teams are sane. But, it's terrible for 2025's median software team. I know that isn't OP's intention. But inevitably, all good advice falls prey to misinterpretation. In contemporary software orgs, build fast is the norm. PMs, managers, sales & leadership want Engg to build something that works, with haste. In this imagination, simple = fast. Let me say this again. No, you cannot convince them otherwise. To the median org, SIMPLE = FAST. The org always chooses the fastest option, well past the point of diminishing returns. Now once something exists, product managers and org leaders will push to deploy it and sales teams will sell dreams around it. Now you have an albatross around your neck. Welcome to life as a fire fighter. For the health of a company and the oncall's sanity, Engg must tug at the rope in the opposite direction from (perceived) simplicity. The negotiated middle ground can get close to the 'simple' that OP proposes. But today, if Engg starts off with 'simple', they will be rewarded with a 'demo on life support'. At a time when vibe coding is trivial, I fear things will get worse before they get better. All that being said, OP's intended advice is one that I personally live by. But often, simple is slow. So, I keep it to myself.
- nojs 1y agoClaude is great at this! If you avoid refactoring at all costs and put everything as close as possible to the relevant code, you maximise the chance it works and minimise pesky DRY complexities.
- mactavish88 1y ago> A lot of engineers design by trying to think of the “ideal” system: something well-factored, near-infinitely scalable, elegantly distributed, and so on. > Instead, spend that time understanding the current system deeply, then do the simplest thing that could possibly work. I'd argue that a fair amount of the former results in the ability to do the latter. There's a substantial amount of wisdom that goes into designing "simple" systems (simple to understand when reading the code). Just as there's a substantial amount of wisdom that goes into making "simple" changes to those systems.
- ocdtrekkie 1y agoOne of my favorite movie quotes is from Scotty in Star Trek: "The more they overthink the plumbing, the easier it is to stop up the drain." Complexity is sometimes necessary, but it always creates more ways things can break.
- fijiaarone 1y agoMostly I agree with what the author is saying. But there is a clear distinction between the simplest “system” and do the simplest thing. The simplest thing to do is almost always the easiest, but knowing what is easiest thing to do is a lot trickier —- see Javascript frameworks. But I think I disagree with the author’s second axiom: “2. Simple systems are less internally-connected.” Creating interfaces is more complex than not. Even if it leads to a cleaner design because of interface boundaries. At the least, creating those boundaries adds complexity, and I don’t mean “more effort”. I mean it in the sense that creating functions is more complex than calling “goto”. And it took decades to invent the mechanism needed to call functions —- which is probably the next most simple thing. However, using call stacks and named pointers and memory separation (functions) leads to vastly improved simplicity of the system as the system as a while grows in complexity. So in fact, using your own in-memory rate limiter may be a simpler implementation than using Redis, but it it also violates the second principle (using clear interfaces leads to simpler systems.) And it turns the author’s first premise — Gunicorn is simpler than Puma. Because Puma does the equivalent of building their own rate limiter — managing its own memory and using threads instead of processes. And Gunicorn does the equivalent of using Redis — externalizing the complexity. What Gunicorn did was simpler to implement (because it relies on an existing isolated architecture - Unix processes and files) but means it has a greater complexity (if you take into account that it needs that whole system to work. However that system is a brilliant set of reductions in complexity itself, but it runs up against limitations and performance at some point. Puma takes on itself more complexity to make administering the server less complex and more performant under load. Also, because it is, in a sense, reinventing the wheel, it lacks the distillation of simplicity that is Unix. So, less internally connected systems are easier to expand and maintain and interface boundaries lead to less complex systems as a whole, but are not, in themselves less complex. Limitations in the system that cause performed problems (like Unix processes and function calls) are not necessarily “more simple than can possibly work” —- but the implementations of those abstractions are not perfect and could be improved. Sometimes it’s not clear where to push the complexity, and sometimes it’s not clear what the right abstraction level is; but mostly it’s about making due with the existing architecture you have, and not having the time or resources to fix it. Until the complexity at your level reaches a point that it’s worth adding complexity at a higher level due to being unable to add the right amount of complexity at a lower level.
- fijiaarone 1y agoMostly I agree with what the author is saying. But there is a clear distinction between the simplest “system” and do the simplest thing. The simplest thing to do is almost always the easiest, but knowing what is easiest thing to do is a lot trickier —- see Javascript frameworks.
- Scubabear68 1y agoI get it. YAGANI. A term coined by consultants who don’t understand an industry who basically say “do the least possible thing that will work” because they don’t understand the domain and don’t understand what requirements are often non-negotiable table stakes of complexity you need to compete. It reminded me of a Martin Fowler post where he was showing implementation of discounts in some system and advocating to just hard code the first discount in the method (literally getDiscount() {return 0.5}). Even the most shallow analysis would show this was incredibly stupid and short sighted. But this was the state of the art, or so we were told. See also Ward Cunningham trying and failing to solve Sudoku using TDD. The reality is most business domains are actually complex, and the one who best tackles that complexity up front can take home all the marbles.
- gavmor 1y agoUndoubtedly, Fowler suggested this as an incomplete step in the development process, essentially to get the code to compile. Incredible that we can tar both complexity and simplicity with the brush of "consultant BS."
- zahlman 1y agoA better explanation of this is on my blog todo list, but: > Even the most shallow analysis would show this was incredibly stupid and short sighted. Why? Yes, there's a high probability that this single line of code is ultimately wrong. But having it allows for testing the system (to ensure that getDiscount gets called, that the resulting price is between zero and the undiscounted price, etc.) and it can trivially be replaced when the actual discounting logic becomes known. Nothing can reasonably be called "short sighted" that doesn't actually limit you in the future. > See also Ward Cunningham trying and failing to solve Sudoku using TDD. It was Ron Jeffries who was struggling with Sudoku, not Ward Cunningham. And he didn't struggle because of "doing simple things", but because he didn't actually know how to solve Sudoku, and rather than doing research (or trying a few by hand and reflecting on his own thought process) he expected to gain special insight into the solver by modeling the problem more accurately. If he had actually known, then he would have just applied the same techniques to modeling the solver, and avoided all the embarrassment. TDD is orthogonal to "doing the simplest thing", just preached by many of the same people. The problem isn't with writing tests for early iterations of the project that aren't anywhere near fully functional. The problem is that the making the tests pass doesn't actually teach you anything about what the next step of functionality is. You still have to actually think, and Jeffries didn't have a proper basis to ground his thinking. Norvig's approach to the problem involved some clever hacks that aren't necessarily the best thing from a code maintainability standpoint. But he resisted the temptation to create a prematurely generalized system for solving constraint-propagation problems, trying to create some generic abstract representation of a "constraint" etc. In essence, that code didn't diverge from what the XP gurus preached; it just didn't follow their specific methods ("OO" modeling that's heavily based on creating new classes, TDD etc.). I independently came to the same conclusions about how to solve the problem, however many years ago. Recently, I was reminded of the story (I think via https://news.ycombinator.com/item?id=42953168 https://news.ycombinator.com/item?id=42953168) and tried writing a solver from scratch as an exercise. My code was certainly not as "clever" as Norvig's, but only a bit longer and IMO much better factored.
- smitty1e 1y agoI call it the "Ditt-Kuh-Pow", the Dumbest Thing That Could Possibly Work. Said that in in a telephone call one time, and the guy leading that was all "I'm mildly disturbed that you had a verbalization for that."
- anonu 1y agoThe problem is sometimes you don't get the right feedback to know when to stop building.
- kid64 1y agoThe author should actually design a successful large software system and try again.
- wanderingmind 1y agoThis consistent with Gall's law, that says complex systems that work can only be achieved by building complexity over simple systems. Complex systems built from scratch do not work. So build the simplest system that works and then keep adding complexity to it based on requirements
- journal 1y agountil? what's the threshold here? does complexity have a final boss?
- journal 1y agoi want to hear an input from winapi team on this.
- arthurofbabylon 1y agoUseful principle. But… (sorry to make a simple phrase more complex) the notion just scratches the surface of complexity management. I appreciate “Philosophy of Software Design” by Ousterhout. I recently read that while rebuilding a text editor. Mind blowing experience. There is a lot of opportunity to more tightly encapsulate logic, to more clearly abstract a system, to keep a system simple yet powerful and extensible. I believe I became twice as good of a developer just by reading a chapter a day and sticking with the workflow.
- kmoser 1y agoNot arguing against this article but aren't all these ideas already well known in the industry? Start with an MVP, don't optimize prematurely, avoid writing brittle code (systems, really), abstract implementation details away when possible, and KISS.
- m463 1y agoHonestly, this is how all computing works. For example, chips just barely work. If they work too well, you could shrink the chip until it barely works making it cheaper or faster or use less power. That said, although this exercise is kind of interesting - like playing jenga - it might not be fun or satisfying. better faster cheaper - sometimes you need to choose better.
- zahlman 1y ago> For example, chips just barely work. This seems a bit overstated (except perhaps for certain recent Intel fabs) considering that they do billions of operations per second and a single error could completely invalidate a complex system in the worst case.
- Leo-thorne 1y agoWe once rebuilt an old system and went with the simplest thing that could work. It ran great for the first few weeks, but then all kinds of edge cases started creeping in. We ended up spending more time patching things up.
- deleted 1y ago[deleted]
- GarnetFloride 1y agoIt seems like a lot of people think that the first draft/prototype/whatever has to be perfect. It doesn't. It never is. It can't be. My favorite example of this was the Moon shot. Each step was learning how to do just that one step. Mercury was just about getting into orbit, not easy even now with SpaceX though they are standing on the shoulders of those giants. Then Gemini for multiple people and orbital maneuvering (that experience gained them lots of learning) and then Apollo 8 was still a dress rehearsal even though they flew around the Moon. Each step HAD to be simple because complexity weighed too much. But each of those simple steps were still wildly complex. Every time I would dive in and code up something that I though was easy, it would blow up in some weird way, and I have found that doing each step individually and getting it right, might sound like I was going really slow, but it was smoother so it was faster in the end because I wasn't chasing bugs in all the places, but just one.
- msephton 1y agoThere is a sign on a wall at Apple that reads: "Simplify. Simplify. Simplify." (with the first two struck out) https://www.forbes.com/sites/kenmakovsky/2012/12/06/inside-apple-2/ https://www.forbes.com/sites/kenmakovsky/2012/12/06/inside-a...
- Nevermark 1y agoLooking over the threads running here, it is interesting how differently the article's title/point is being taken, filtered through different commenter situations and experiences. I don't see it as a blind prescription. It doesn't imply that choosing what is simple, will be simple. Or that simplest, will be simple. Or that this is a process uniquely immune from problems or tradeoffs. Just a reminder to never forget to aim for simplest. A tautological cookie fortune, of something important we often functionally forget or slide on. There is a lot of wisdom in recognizing and repeating the most important "mantras of the obvious". And listening to them reformulated, in other ways, by other people. The greatest craftbeings never stop revisiting the basics.
- travisgriggs 1y agoAll too often I see this mantra used to justify doing the “easiest thing that could possibly work.” Which in my experience is not the same thing. They can overlap, and often upstream simplicity can create a downstream effect of ease for consumers. Simplicity often requires some real effort to execute well.
- bubblyworld 1y agoSimplicity is brittle. Perhaps we should take a page from nature. Nothing in nature in simple, and yet it has built some of the most robust systems (by far) that we know of. Can your software run for millions of years?
- tim333 1y agoThe sun is basically a ball of hydrogen that fuses into helium but it seems to be hanging in there.
- bubblyworld 1y agoThe sun doesn't solve any problems in a useful sense. I'm talking about life! I thought that would be obvious haha.
- dlenski 1y ago> A lot of engineers design by trying to think of the “ideal” system: something well-factored, near-infinitely scalable, elegantly distributed, and so on. Was it Donald Knuth who said "premature optimization is that root of all evil"? This article made this point very well, especially regarding the obsession with "scaling" in the SaaS world. I've seen thousands and thousands of developer hours completely wasted, because developers were forced to massively overcomplicate greenfield code in anticipation of some entirely hypothetical future scaling requirement which either never materialized (95% of the time) or which did appear but in such a different form that the original solution only got in the way (remaining 5%). John Ousterhout’s Philosophy of Software Design makes the case for simplicity in a book-length form. I really like how he emphasizes the importance of design simplicity for the maintainability of software; this is where I've seen it matter the most in practice.
- atomicnumber3 1y agoMy current company is in that 5% part right now. Tremendous effort invested into the system, everyone involved was very proud of themselves. Unfortunately the way we actually needed to scale was almost completely untouched by any of this architecture astronomy, so we have both a terrifically complicated system - very difficult to change things without potential breakage or regression - AND it doesn't scale at all. I don't mind, I don't blame people for not predicting the future - it's a tough game. But god the hubris and attitude we put up with until the crows came home to roost.
- froh 1y agothanks for sharing and I couldn't agree more. I assume you mean astrology (prophecy), not astronomy (science)?
- dlenski 1y ago> I assume you mean astrology (prophecy), not astronomy (science)? I took "astronomy" as an allusion to the fact that @atomicnumber3's team was metaphorically peering at their scaling needs through a telescope, an instrument with a very narrow field of view.
- signa11 1y agohard disagree (fwiw). this *tactical* style of development is the same thing propounded by TDD folks. there is no design, just a wierdly glued together mishmash of things that just happen to work. i am (fwiw once again) not against unit-testing, that is almost always needed.
- del_operator 1y agoGet it out. Make it work. Love your work.
- cyprx 1y agoit won't work when every single PRD now has the word "extensible". i think overcomplexity often comes from requirements/ business usecases first
- cmertayak 1y agoIt nails the value of keeping things simple, and I think the link to cognitive load deserves even more emphasis. In most of the cases, simplifying means reducing the cognitive load. Sometimes consolidating pieces with DRY, sometimes using design patterns, sometimes decomposing things into services... Every extra details or workaround increases the number of things you need to keep in your head, not just when building the system, but every time you come back to maintain or extend it. "Simple systems have fewer 'moving pieces': fewer things you have to think about when you're working with them." Simplicity isn't just about getting the job done quickly; it's about making sure future you (or someone else) can actually understand and safely change the system later. Reducing cognitive load with simplicity pays off long after the job is done.
- cranx 1y agoI think a lot of engineers think, “I thought of a complicated set of abstract ideas that mean nothing to anyone else but will demonstrate my superior intellect” and then make that. It took a lot of self control to not curse.
- michalc 1y ago> real mastery often involves learning when to do less, not more Really love and agree with this, and (shameless plug?) I think really aligns with a way of working I (and some colleagues) have been working on: https://delivervaluedaily.dev/ https://delivervaluedaily.dev/
- motorest 1y agoI think this article actually expresses a dangerous, risk-prone approach to problem solving, and one which ultimately causes more problems than the ones it solves. The risk is misunderstanding the problems they are solving, and ignoring all the constraints that drove the need for some key design traits that were in place to actually solve the problem (i.e., complexity) Take the following example from the article: > You should do that too! Suppose you’ve got a Golang application that you want to add some kind of rate limiting to. What’s the simplest thing that could possibly work? Your first idea might be to add some kind of persistent storage (say, Redis) to track per-user request counts with a leaky-bucket algorithm. That would work! But do you need a whole new piece of infrastructure? Let's ignore the mistake of describing Redis as persistent storage. The whole reason why rate limiting data is offloaded to a dedicated service is that you want to enforce rate limiting across all instances of an API. Thus all instances update request counts on a shared data store to account for all traffic hitting across all instances regardless of how many they might be. This data store needs to be very fast to minimize micro services tax and is ephemeral. Hence why a memory cache is often used. And why do "per-user request counts in memory" not work? Because you enforce rate-limiting to prevent brownouts and ultimately denials of service triggered in your backing services. Each request that hits your API typically triggers additional requests to internal services such as memory stores, querying engines, etc. Your external facing instances are scaled to meet external load, but they also create load to internal services. You enforce rate-limiting to prevent unexpected high request rates to generate enough load to hit bottlenecks in internal services which can't or won't scale. If you enforce rate limits per instance, scaling horizontally will inadvertently lift your rate limits as well and thus allow for brownouts, thus defeating the whole purpose of introducing rate limiting. Also, leaky bucket algorithms are employed to allow traffic bursts but still prevent abuse. This is a very mundane scenario that happens on pretty much all services consumed by client apps. Once an app is launched, they typically do authentication flows and fetch data required in app starts and get data, etc. After app inits the app is back to baseline request rates. If you have a system that runs more than a single API instance, requests are spread over instances by a load balancer. This means a user's request can be routed to any instance at an unspecified proportion. So how do you prevent abuse while still allowing these bursts to take place? Do you scale your services to handle peak loads 24/7 to accommodate request bursts from all your active users at any given moment? Or do you allow for momentary bursts spread across all instances, regardless of what instances they hit? Sometimes a problem can be simple. Sometimes it can be made too simple, but you accept the occasional outage. But sometimes you can't afford frequent outages and you understand a small change, like putting up a memory cache instance, is all it takes to eliminate failure modes. And what changed in the analysis to understand that your simple solution is no solution at all? Only your understanding of the problem domain.
- progx 1y agoDo something simple. Dream vs. reality.
- aryehof 1y ago> Do the simplest thing that could possibly work … That advice these days surely means having an LLM vibecode a mess of something? Is such obvious and unquantifiable advice actually useful?
- zkmon 1y agoPrinciples like these deserve to be part of curriculum for undergrad courses. People are incorrectly trained to go for some ideal forms at the cost of complexity and fragility. Every approach, idea should be put to ruthless cost-benefit comparison, without any regard to who is proposing it, or how it sounds. Education and training sometimes enforces prejudices, rules and stigmas that evade inspection of the subject matter in raw form. Preference to idealism probably emerged from peace times which have no struggle. Someone would be obsessed with perfectness of a sculpture only when they don't need to hunt for the next meal. The real world runs on minimal, conservative, durable and robust approaches.
- randyrand 1y agoif only designing simple systems as it’s easy as it sounds. it takes maybe 3 to 5 rewrites before you truly grasp a problem.
- moffkalast 1y agoNooo you can't use deterministic math, you gotta use kalman filters and particle filters and factor graphs and spend three months tweaking parameters to get a 5% improvement! /s Like alright in some situations that's the only thing that could possibly work, but shoving that complexity into every state estimator without even having a way to figure out the actual covariance of the input data is a bit much. Something that behaves in an expected way and works reliably with less accuracy beats a very complex system that occasionally breaks completely imo.
- mcv 1y agoIt's important to understand the difference between easy and simple. It's easy to add complexity, it can sometimes be hard to keep things simple. But with that in mind, I do agree that a lot of systems are more complex than they need to be. I like to keep things simple. Of course scalability adds complexity, and sometimes you need that. But you don't always need that, and making things scalable that don't need to be, makes them harder to understand and maintain.
- stpedgwdgfhgdd 1y agoXP
- metanonsense 1y agoI would be very cautious to give an advice like this to my team. Making a thing simple is actually very hard, and many, who hear the words, may just equate „simple thing“ with „first thing that comes to mind“, which may eventually turn into a nightmare of complexity.
- tanelpoder 1y agoWhen I'm on the fence about some (technical) decision, I use a "razor": if all options seem equal, go with whichever is the simpler one. The results are ok so far and it has been great for reducing my brain-energy spent on pontification and early optimization too far ahead. I liked the post, but these kinds of articles do make sense to people who've already been through the trenches & view the advice from their seasoned experience PoV and apply it accordingly. But if people without such experience follow it to the letter just because it's written, can have surprises ahead.
- jchook 1y agoObligatory reference to Simple Made Easy https://www.infoq.com/presentations/Simple-Made-Easy/ https://www.infoq.com/presentations/Simple-Made-Easy/ I watch this talk about once per year to remind myself to eschew complexity.
- yehat 1y agoThat principle is valid also outside the software engineering domain. Except for German engineers...
- nickm12 1y agoThis piece is arguing against what is often called "over-engineering" or unnecessary abstraction (YAGNI). Over-engineering is a problem in software systems because it generally takes longer to build and it makes the systems unnecessarily more difficult to understand. While a problem, I don't think it is the most important design issue I see in software systems. The bigger problem I see is lack of abstraction, or systems where the components have too much knowledge of each other. These are fast to build and initially work just as well as the more "heavily engineered" systems. However as the code evolves to meet changing requirements, what happens is that code becomes more complex, either through even more coupling or through ad hoc abstractions that get implemented haphazardly. It can be really difficult to know where to draw the lines, though. When you are trying to decide between a simpler and more complex option, I think it's worth starting with the simplest thing that could possibly work, but build it in a way that you can change that decision without impacting the rest of the system. On a tangent, I'm not a fan of Uncle Bob (to put it mildly) but this topic makes me think of his quote "a good architecture allows decisions to be deferred". I would restate it as "a good architecture allows decisions to be changed in isolation".
- matthewsinclair 1y agoIt's worth quoting "Gall's Law" [0] here: > “A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over with a working simple system.” I have this up on my wall and refer to it constantly (for both tech and non-tech challenges). [0]: https://blog.prototypr.io/galls-law-93c8ef8b651e https://blog.prototypr.io/galls-law-93c8ef8b651e
- bob1029 1y agoIf we were willing to abandon all of our tooling and technology tribalism, it would become feasible to replace many B2B SaaS products with a scheduled ETL job that runs on an MSSQL or Oracle box once per day. Most business processes can be modeled as extract-transform-load. The business would generally agree that fancy spreadsheets on the server is much simpler compared to a custom codebase. Especially, when granted access to this data and involved in its schema design.
- conradfr 1y agoIt often feels like a large part of the dev world is just coding some fancy gui & system for what could be (or used to be) Excel + Access :)
- jdblair 1y agobut it was so much fun to write my own serial networking protocol! and my 2nd stage bootloader for arduino! ...and by the time I finished, the esp32c hardware was released and I didn't need it anymore.
- daitangio 1y agoRight in theory hard to do in practice. Also business needs are awful complex, guys.
- Gehinnn 1y agoIs doing a refactoring ever the simplest thing that could have been done? I think "do the simplest thing" should be "do the thing that increases complexity the least" (which might be difficult to do and require restructuring).
- 867-5309 1y agoinstructions unclear return segfault -1;
- zduoduo 1y agoIndeed, this is a good way
- silverkiwi 1y agoCopy/Paste save as system prompt
- silverkiwi 1y agoCopy/paste/save as system prompt
- phendrenad2 1y agoI think there's a natural rhythm to complexity. After a tech crash, everyone abandons what are generally regarded as best practices, and just writes scrappy code, I.E. the "simplest thing". Then, there's a backlash against it, and consultants make a lot of money teaching people how to avoid "code smells". Then a bubble forms and code quality stops mattering much relative to marketing and sales effectiveness.
- dihedihe 1y agoBroblim
- austin-cheney 1y agoSimplicity applies universally and is almost always more correct. Simple just means the option of fewer steps. Simple does not mean easy, so therefore simplicity as a principle is always objective and measurable. Where people fail on this most frequently is reasoning in first person pronouns whether explicitly or implicitly and whether or not stated, thought, or considered. Simplicity is but merely the result from a comparison of measures. It’s not about you and has nothing to do with your opinion.
- desio 1y agoshouldn't it be "the simplest possible thing that could work"?
- mingtianzhang 1y agoThis is also called occam's razor principle.
- shellkr 1y agoI think I learned this from Arch Linux and their focus on the KISS principle (https://en.wikipedia.org/wiki/KISS_principle https://en.wikipedia.org/wiki/KISS_principle). This is also something that goes beyond the computing sphere. It is really a good principle for life in general.
- Starlevel004 1y agoThe simplest option usually also comes with all the drawbacks of being the simplest option. "Keep it simple" is one of the more irritating thought-terminating cliches.
- janderson215 1y agoSimple rarely means the first thing that comes to mind and is something you have to work towards, so I would think it’s more stimulating than terminating. There is more than one way to skin a cat and using a weed whacker probably isn’t the best. It might even make sense to acquire a new tool.
- tim333 1y agoDunno if it's really thought-terminating. I mean consider Warren Buffett who has gone with a simple strategy of valuing businesses and buying them or parts of them for less than they are worth or buying two dollar bills for a dollar as he put it. There's a lot of thought underlying that though because then you have to understand businesses and as those interact with everything in the world there's understanding that too. So it's simple in some ways and not in others. But it worked well - I think he'd be the world's richest if he hadn't given a load away to charity.
- boricj 1y agoI disagree. You prototype the simplest thing that could possibly work. Then, you design stuff so that you don't end up regretting it later. I happen to have a recent example with an add-on card. For reasons that I won't get into, we needed both insurance against major rearchitecturing, as well as leverage synergy with other product lines when it comes to configuration. That led me to design a fairly intricate library that runs visitors against a data model, as well as a mechanism where the firmware dumps its entire state as a BSON document in a dedicated Flash partition before upgrading. That gave us the peace of mind that whatever happens, we can always just restore from that document and nuke everything else when booting a newer firmware for the first time. The simplest thing that could possibly work would've been to not do any of that and let future firmware versions deal with it. Instead, I designed it so that I don't end up regretting it later, regardless of how the product evolved. The only point I do regret was missing one piece of information to save on the initial release-to-manufacturing version. I had to put in one hack that if the saved document has version 1.0, then go spelunking in the raw flash to retrieve that piece of information where it was in version 1.0 and slipstream it into the document before processing it. Given the data storage mechanism of that platform, I'd be tearing my hair apart dealing with multiple incompatible data layouts across firmware versions if I did the simplest thing.
- froh 1y agoI think your version _is_ the simplest thing that works: software updates are part of what needs to work in embedded. else you brick devices and have to send technicians to the device, right?
- boricj 1y agoThe simplest thing that would've worked was for the initial firmware to do nothing besides putting the new firmware in the secondary slot, tell mcuboot to upgrade and then reboot. That shifts the responsibility of working upgrades to later firmware revisions, at the cost of significant technical debt and extra development costs in the future. My point is that the simplest thing that could possibly work disregards state and time as factors. Good engineers balance all requirements to derive the simplest solution that works; great engineers do so while avoiding visits from irate future colleagues.
- egorfine 1y ago> What’s wrong with doing the simplest thing? Staff. You've got developers and they will continue working on a product oftentimes way past the "perfect" stage. Case in point: log aggregation services like Sentry/etc. It always starts with "it's so complex, let's make a sane log ingestion service with a simple web viewer" and then it inevitably spirals into an unfathomable pile of abstractions and mind-boggling complexity to a point where it is literally no longer usable.
- PickledChris 1y agoThis is an interesting point, but there's slightly more to it than that. When something is simple and does the job well, it has limitations. The problem is that adding each subsequent feature has a small benefit and a small, but immeasurable cost. Sometimes that cost outweighs the benefit, but knowing that before the fact is very hard, and removing features is almost impossible as people shout disproportionately loudly about losing things. It's similar to the problem of regulation. Looking at each individual law, it often seems reasonable. It's only when there are 10,000, and everything grinds to a halt, that people realise there's a problem.
- egorfine 1y agoTrue. IMHO the log services example is excellent to illustrate this: the path that leads to their hairball of complexity is perfectly clear and every solution they do is extremely logical and obvious. This is why these services are so much similar. But the end result is always too complex and it seems to me that "perfect" point does not exist for this line of products.
- sarchertech 1y agoEverything is a trade off and experience is knowing when it’s worth it to add a hook for future expansion and when you can wait. The problem is that when you let people without experience design things, they tend towards what I call “what if driven development”. At every point in the design they ask what if I need to extend this later. Then they add a hook for that future expansion. When we are training juniors the best thing is not to show them all the best practices in Clean Code because most of them gravitate towards overengineering anyway. If you give them permission and “best practices” to justify their desires, they write infuriatingly complicated layers upon layers of indirection. The thing to do is to teach them to do the simplest thing that works—just like this blog post says. Will that result in some regrets when they build something that isn’t extensible? Absolutely! But it’s generally much easier to add a missing abstraction than it is to remove a bad one.
- sdeframond 1y agoIn civil engineering they say that "Any idiot can build a bridge that stands, but it takes an engineer to build a bridge that barely stands.”
- egorfine 1y agoAn extremely important classic to consider: https://www.joelonsoftware.com/2001/04/21/dont-let-architecture-astronauts-scare-you/ https://www.joelonsoftware.com/2001/04/21/dont-let-architect...
- sesm 1y agoAuthor's definition of simplicity is self-contradictory: fewer moving pieces result in highly-specialized monolith systems, while breaking up everything into components with clear interfaces results in more moving pieces.
- deleted 1y ago[deleted]
- anon6362 1y ago- Robust - Simple - Easy - Fast - Understandable by mere mortals - Memory efficient - CPU efficient - Storage efficient - Network efficient - Safe Pick up to 3
- rossdavidh 1y agoI have worked at places where, for a website that would require one server (or at most two or three, for redundancy), Kubernetes and React and all the trappings of a humongous website were implemented. It took me a bit to figure out why we were doing all this for a website which would basically just publish some static html: it was for resume building. The lead dev, and the project manager, were not working on that project (a website which would never get all that big), they were working on a resume for FAANG. Once you see this, you see it everywhere. 90% of the places using "modern" web technology, are built as if they were anticipating FAANG scale, not because they are, but because the people building them hoped to be working at FAANG soon.
- plxio32 1y agoI have 100% the same experience. I would say it's often also an ego thing, not only resume building. I.e. the ego can't handle building a simple solution, the dev builds FAANG scale solutions therefore he/she is a great developer.
- dondraper36 1y agoEven in this thread, there was a comment (now deleted) saying that a staff engineer at GitHub is unlikely to know what real scale is.
- cratermoon 1y agoWe had this discussion around "the simplest thing" way back in the late 90s/early 2000s when XP was getting started. One comment I remember well is, "it's do the simplest thing, not the stupidest thing". Maybe a boring relational database is the simple thing, compared to some distributed eventually consistent map-reduce system using HDFS. Or maybe a simple key-value store like Memcached is all you need. Even in complex domains, the aphorism, "everything should be made as simple as possible, but not simpler" applies. As for working at scale, complex systems are made of small, simple, working systems, where dependencies between them are limited and manageable. Without an effort to keep interdependencies simple, the result is a Big Ball of Mud, and we all know how well that works.
- sltr 1y agoI'm feeling surprised that ao far nobody has mentioned Fred Brooks' essential vs incidental complexity.
- evelant 1y agoThe more years I've been developing software (and it's been awhile) the more I come to find that the answer is almost always "it depends". The definition of "simple" depends on the case, the requirements, and the level of uncertainty about the future. The definition of "complex" depends on the case, the requirements, and the level of uncertainty about the future. I've run into a lot of situations where doing the "simplest thing that could possibly work" ultimately led to mountains of pain and failure. I've also run into situations where things were over-engineered to account for situations that never came to be resulting in similar pain. It boils down to "it depends" -- a careful analysis of the requirements, tradeoffs, future possibilities, and a mountain of judgement based on experience. For sure, err on the side of "simple" when there's uncertainty but don't be dogmatic about it. Apply simple principles like loose coupling, pure functions, minimal state, avoid shared state, pick boring tools, and so on to ensure that "the simplest thing that could possibly work" doesn't become "the simplest thing that used to work but is now utter hell in the face of the unexpected". It all depends.
- rectang 1y ago"I have made this longer than usual because I have not had time to make it shorter." — Blaise Pascal I fully agree with the author about the desirability of simplicity. I feel it in my bones, as someone with a background in the arts who has spent endless hours agonizing over tiny details and discarding perfectly good sections which nevertheless did not serve the whole. What this article doesn't emphasize is that simplicity has cost. Shaving down a pile of yak hair isn't enough to reveal Brancusi's Bird in Space[1] — it needs to be visualized from multiple angles, tested, reshaped, re-imagined over and over. In engineering, simplicity is one more axis to optimize against. For systems that endure, some measure of time spent simplifying will be worth it. But I find that when I make that argument, my case is strengthened by bearing in mind the size of the spend. [1] https://upload.wikimedia.org/wikipedia/commons/6/69/Bird_in_Space.jpg https://upload.wikimedia.org/wikipedia/commons/6/69/Bird_in_...
- bwfan123 1y agoI would disagree with the premise of this article. All this talk of simplicity may mislead one into building something that just about works, and calling it a day. I believe that is a mistaken approach in science and engineering. Instead, there should be a deeper understanding of the limits and constraints on the problem. In my view, the focus should be on the problem and its constraints rather than on the nature of the solution. An analogy in terms of algorithms would be: Why take the pains to implement an O(nlogn) solution to sorting when you can implement a O(n^2) solution which is far simpler. ie, be satisfied with a feasible solution instead of seeking what could be more optimal. The road to interesting insights may not be linear and incremental. Doing the simplest thing at all times is an incremental greedy approach.
- oldslang 1y agoAs a PM focusing mostly on new product development, my mantra to engineering was "Do the easy, cheap stuff first." The corollary was, "If we are very lucky, we will live in regret because the product has taken off but the architecture is now obviously wrong." This was understandably frustrating to many engineers because they wanted me to have a certainty about the correctness of what we were building that I just never had. Every good idea I had for product emerged over time, often years and countless false steps. I could never figure out how to avoid the false steps so the goal became to keep cost and effort down along the way.
- ianberdin 1y agoI name it: use the sharp knife instead of building Combine Harvester.
- aleksiy123 1y agoI've realized that people have different understandings/definitions of what "simple" means. Many people think "simple" is equivalent to easy/fast. It often isn't. Often complexity is actually easy/fast. But simple is hard as it requires deeply understanding the problem, and fitting the right solution to where there is nothing to "simplify".
- mahirsaid 1y agoIdeas are simple, and so on. i don't understand the reason behind complicated coding to make an app/service so buggy. at this point there are plenty of already practiced true implementations.
- perilunar 1y ago“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” — Antoine de Saint-Exupéry, Terre des hommes, 1939
- paulified 1y agoI think if you keep in mind we're talking simple and not easy, then it's sort of like "of course". And there's definitely a sort of elegance in a simple design, like how Apple does hardware, that still manages to "get the job done". So in that sense it's more of a considered constraint than neglect. But I think there's also a danger of this becoming cargo-culted/dogmatic to the point where's it _is_ the messy, short-sighted solution. I remember many years ago working at a company that adopted XP and TDD and the whole "write the failing test and then the simplest thing to make the test pass". Well-intentioned but with some experience you quickly realise that sure, just returning a hard-coded value will make the test pass simply, but I _know_ there's more requirements coming and that code's going to have to change. So to with system design, I suspect there's also a case for experience telling you that the changes are coming. Maybe this still fits into the "possibly work" part. The other thing I've seen in my time is that you don't always get the capacity to come back change the design later. So while it's great (and probably bordering on being clever for clever's sake) at times to do the simple thing, hedging your bets in terms of how a system will have changes piled on can often be a good move too. I think that the main issue with these kind of concepts is they always sound great on the face of them but in the real world it's never that simple :P