[HN Gopher] Do the simplest thing that can possibly work (2004)
___________________________________________________________________
Do the simplest thing that can possibly work (2004)
Author : TacoSteemers
Score : 125 points
Date : 2023-02-28 10:14 UTC (12 hours ago)
(HTM) web link (twasink.net)
(TXT) w3m dump (twasink.net)
| buescher wrote:
| What I frequently see is "the simplest thing that could plausibly
| work"
| irrational wrote:
| I've learned that when I ignore things, they often go away. That
| is the kind of simplicity that has served me well for decades as
| a developer.
| loudmax wrote:
| Rich Hickey's Simple Made Easy presentation is a fantastic
| introduction to this philosophy:
| https://www.infoq.com/presentations/Simple-Made-Easy/
|
| Simple isn't the same as easy, and it isn't always obvious where
| the complexity is. One should beware of "simple" solutions that
| either hide the complexity, or shove it someplace else. The skill
| is to identify and minimize _unnecessary_ complexity, which is
| another way of phrasing "Do The Simplest Thing That Can Possibly
| Work".
| mattbuilds wrote:
| Thanks for this, it's great. I've never explained it as clearly
| as these two do, but this has always been my philosophy and
| what I try to aim for when developing software. I find that a
| lot of times people opt for easy, thinking that it's simple,
| but down the road they find out it is actually complex. I
| wonder if we will every see a real shift to focusing on
| simplicity and the gains that come from it?
| hummus_bae wrote:
| [dead]
| addaon wrote:
| This write-up is too light to provide any real insight. In
| particular, how do you assess simplicity?
|
| From an example I'm currently working through on a hobby
| project... do I use a RS-485 transceiver with a custom line code,
| or do I use a 10base-T1 PHY? Ethernet, especially one pair
| ethernet, is undoubtedly more /complex/, with echo cancellation,
| a complicated line code, etc; but if I use the PHY, then /I own/
| that complexity.
|
| (For pure software folks, the equivalent question is internal
| implementation vs external dependencies. Do you implement a 1D
| barcode yourself, or do you import a third-party dependency for
| QR code reading?)
|
| The problem is that answering this depends not on some objective
| notion of simplicity, but on a realistic assessment of /where
| time will go/ during the development process. If development time
| dominates, then exporting complexity is a win. But if testing
| time dominates, and since exported complexity still needs to be
| fully understood during testing, then in-house simplicity wins.
|
| And which of these cases dominates is very much a project-by-
| project and team-by-team decision.
| dfxm12 wrote:
| _The problem is that answering this depends not on some
| objective notion of simplicity, but on a realistic assessment
| of /where time will go/ during the development process._
|
| I don't think anyone mentions time as a proxy for simplicity.
| At least, the article certainly doesn't. You're right that the
| author doesn't objectively define simplicity, but I don't think
| anyone can. What is simple tends to be different to different
| people/teams, based on skills, tools, etc., available.
|
| I know what's simple to me. I know it may not be simple to you.
| I know what's simple for a team in my org and I know it may not
| be simple for another team in another org. But, I do know what
| skills someone in my position and in my org is expected to
| have, and I know what tools are available to us, so I can make
| some real assertions here about what is "simple". Get worried
| beyond that, and you get bogged down on unknown unknowns.
| moremetadata wrote:
| > the equivalent question is internal implementation vs
| external dependencies.
|
| Liabilities. Take the Windows EULA, its a contract that states
| MS is not liable for anything, standard software contracts
| state the same, so if boils down to being able to prove
| negligence, which can be sued for.
|
| For example, do you trust the suppliers? IF they are in a
| different country, what's the chance of legal recourse if
| negligence can be proved, knowing about political interference
| if the entity is valuable enough?
|
| So yes I agree, how do you assess simplicity, and as Billy
| Gates would say... it 's complicated!
| csdvrx wrote:
| For me, the simplest thing would be using a serial interface
| instead!
| addaon wrote:
| RS-485 is a serial interface, at the physical layer.
|
| 8N1 as a line code introduces all sorts of other issues,
| assuming you're passing messages instead of byte streams over
| it. In particular, how do you do packetization? How do you
| synchronize? So many "serial interfaces" have implicit timers
| (corresponding to interpacket gap for ethernet) used for
| sync'ing, or play horrible games with embedded CRCs...
| there's a huge amount of hidden complexity here, especially
| if you do it implicitly without understanding the
| dependencies.
|
| By the time you've solved reliable packetization over 8N1,
| you're going to have something that looks a lot more like an
| Ethernet-level-complexity line code.
| majkinetor wrote:
| Simple is something that either can't be reduced further
| without changing the output (ideal, simplest), or it is very
| hard to do so (real world).
| addaon wrote:
| But this ignores, as in my example, who pays for the
| complexity.
|
| I want a bagel. Is it simplest for me to start tilling the
| land and looking for wild wheat relatives to breed, or to
| drive my incredibly complex car built in centuries of
| industrialization to the corner store and buy (using money,
| one of the most complex concepts we've developed!) a bagel,
| bring it home in a plastic (!!!) bag, and stick it in the
| toaster?
|
| If I should, during my lifetime, succeed in completing a
| bagel with the former, I have reasonable confidence it can't
| be reduced further without changing the output.
|
| But I disagree that it's the simplest way /for me/ to get
| breakfast.
| Zetice wrote:
| I don't think the person you're replying to would consider
| "till the land" as fitting what they're describing as
| "simple".
| addaon wrote:
| It's a requirement for making a bagel... the question is
| whether I do it, or someone else. Part of the irreducible
| complexity of bagelness is the production process of
| wheat.
| jacobr1 wrote:
| It is a good way to consider the extremes of the problem-
| space, which often is a good way to come at a problem.
|
| But a more practical, analogous situation might be:
| should I buy a nice, warm bagel at the local bagel shop,
| or should buy it a store and toast it myself? In that
| trade-off I can take for granted that I'm getting a
| bagel, but the delivery mechanism, the quality, the
| integration options, the cost, are things I need to
| consider.
|
| The decision will depend upon your requirements. If you
| are organizing an event, maybe I get some bulk catering
| from the bagel-shop. If you want to use your aunt's
| bespoke berry jam, maybe you use the store-bought bagel
| so you easily can use your home spreads.
|
| Identifying the optimal simplicity can be a hard problem,
| but that shouldn't preclude narrowing down choices with
| some rough heuristics so that you don't need to
| investigate the combinatorial explosion of all
| possibilities, or rethink the system dependencies back
| to: "first we have a big bang."
| majkinetor wrote:
| You are not producing a bagel. You are obtaining it.
| There is a big difference. Once nobody produces a bagel,
| your method is meaningless.
| Zetice wrote:
| I'm not sure how you arrived at "every single step
| involved must be considered" from "can't be reduced
| further".
|
| If a step available to you is "buy a bagel", that's all
| you have to consider.
| addaon wrote:
| At the risk of beating an analogy to death... this is
| exactly the mental model that gets us leftpad.
| Outsourcing of complexity is /not/ elimination of
| complexity. I may go my whole life without having to
| debug the lower-level steps in the process that put a
| bagel on my table, and if that's the case then treating
| dependencies as zero-cost makes sense -- but also, I may
| not be so lucky. When the supply chain collapses, I have
| to go without my bagel, or dig deeper. Either of which
| may be fine, depending on my requirements -- but the
| exported complexity is now present and impacting my
| experience.
| Zetice wrote:
| There's nothing wrong with leftpad as a library concept.
| The problem was that it got hacked, not that it does
| something useless that everyone should write on their
| own.
|
| leftpad was incorporated into ECMAScript in 2017 for a
| reason.
|
| > Outsourcing of complexity is /not/ elimination of
| complexity.
|
| This is technically true but functionally false. You're
| literally arguing against the concept of abstraction
| layers, while writing text into a form built on top of
| hundreds of them.
|
| There are two thoughts I have regarding this:
|
| 1) Leaky Abstractions seems like what you're trying to
| point out, and accurately so [0] but,
|
| 2) you can still rely on even leaky abstractions. You
| must, in fact, to function in this world. In some ways
| the quote, "In preparing for battle I have always found
| that plans are useless but planning is indispensable" [1]
| applies to abstraction as well.
|
| [0] https://www.joelonsoftware.com/2002/11/11/the-law-of-
| leaky-a...
|
| [1] https://quoteinvestigator.com/2017/11/18/planning/
| addaon wrote:
| > You're literally arguing against the concept of
| abstraction layers, while writing text into a form built
| on top of hundreds of them.
|
| Sorry, I see how what I said could have been interpreted
| this way. That's /definitely/ not my intent, and I'd like
| to clarify.
|
| I am arguing that abstraction layers have cost, and
| (independently) that third-party dependencies have cost.
| (Abstraction layers are a great tool for isolating third-
| party dependencies, so they tend to go together, but
| they're independent things here.)
|
| Also, lack of abstraction layers has cost, and building
| everything in house has cost.
|
| These costs need to be traded. In some cases, leaning on
| external dependencies is the right choice. In other
| cases, it's not.
|
| If complexity (opposite of simplicity) under an
| abstraction layer is neglected (estimated at zero), using
| simplicity as a guideline for making engineering
| decisions will lead you to the wrong decision some of the
| time. Similarly, if complexity under an abstraction layer
| is treated as just as non-simple as complexity above the
| abstraction layer, using simplicity as a guideline will
| lead you to the wrong decision some of the time.
|
| Therefore, "the simplest thing that can possibly work" is
| too naive a metric to be used for making decisions (as
| opposed to just for justifying decisions you already want
| to make). It takes a more nuanced discussion of types of
| simplicity, and whether complexity is being eliminated or
| just hidden, and if it's hidden how likely it is to stay
| hidden, to make this rule useful.
|
| For the record: I buy my bagels from a store. When the
| roads are closed due to snow, I don't have a bagel.
| That's the right decision for me, unsurprisingly, for
| this problem.
|
| Finally, I'll argue that there /was/ a problem with
| leftpad as a library concept. There is an inherent
| minimum complexity to a dynamically linked external
| dependency. The reduction in complexity of the
| implementation must be at least as large as this cost.
| One can argue about where the line lies (and it depends
| on the maturity of your ecosystem, etc), but I'd take the
| stance that leftpad is too simple to implement directly
| for pushing it to an external dependency to ever e the
| right choice.
| Zetice wrote:
| If your point is, "abstractions don't have zero cost"
| point taken. But if your point is, "abstractions have
| meaningful cost", I'd rephrase that as, "The better an
| abstraction is, the closer to zero its cost becomes."
|
| Can we agree on that?
| addaon wrote:
| Absolutely.
|
| And in particular, I'd like to rephrase my original
| statement of:
|
| > Outsourcing of complexity is /not/ elimination of
| complexity.
|
| to
|
| > Outsourcing of complexity /reduces/ complexity, but not
| all the way to zero.
| Zetice wrote:
| Woo, agreement! And a good point, too!
| kokanee wrote:
| I agree, the article is entirely focused on semantics. In the
| real world, outside of research and education, no one ever
| attempts to make something more complicated than it needs to
| be. A software project consists of thousands of different
| problems with solutions that must be mutually compatible
| through a web of compromises. You have known hard requirements,
| known soft requirements, known future requirements, unknown
| future requirements, and you're searching for the simplest
| possible solutions for each of them that result in something
| like a "minimum net complexity." The problem of "over-
| engineering" comes when a solution that optimized the
| simplicity for one concern becomes incompatible with another
| concern. It's inevitable in any system where requirements are
| subject to change over time.
| xiphias2 wrote:
| Actually Rick Hickey's talk
| (https://www.youtube.com/watch?v=LKtk3HCgTa8) is amazing
| because he talks about your case by going back to the original
| meaining of words:
|
| ,,Complex comes from the Latin complecti, which means "to
| entwine around, to embrace''
|
| Simplicity requires layering, so in your examples the main
| requirement for simplicity is about how intertwined your hobby
| project is with the transciever code or ethernet code.
|
| As long as the abstraction layer works well for you without
| getting too much into the details of the implementation, it's a
| simple solution.
|
| Of course it's not a clear answer whether you should do things
| yourself or use a third-party, but if the third-party works
| perfectly for use case without significant tradeoff in your
| system, of course it's better to use it.
| majkinetor wrote:
| > As long as the abstraction layer works well for you without
| getting too much into the details of the implementation, it's
| a simple solution.
|
| You can have very large number of layers, and to understand
| inner goings and interconnetions of all becomes very hard.
|
| I highly doubt you can equalize "set of superb interfaces"
| with simplicity.
| xiphias2 wrote:
| You're totally right. Just watch the video, I can't compete
| with Rick Hickey. I just rewatched it and would probably
| modify what I wrote, but the main point is: it's better to
| not write a summarizing article or comment when that video
| is so great, so I won't try to write something smarter
| (rather try to apply the things he said in the video).
| addaon wrote:
| > As long as the abstraction layer works well for you without
| getting too much into the details of the implementation, it's
| a simple solution.
|
| But this is where the engineering intuition has to come in.
| "As long as you will not end up spending more time debugging
| the system than implementing it" is an equivalent statement
| -- and that requires prediction of the future. If I'm going
| to spend hours staring at signals on a 'scope to debug the
| system, I'd way rather they be RS-485 than 10base-T1, for
| reasons of simplicity -- but I don't know, today, if I will
| or not.
|
| Layering works /great/ during implementation. Layering is a
| strong impediment to understanding during testing and
| debugging. Debugging a system efficiently requires being able
| to bridge between layers of the system and see where your
| assumptions break down. And once you're going between those
| layers, you're exposed to the complexity within them.
|
| So: simplicity in implementation, or simplicity in debugging?
| marcosdumay wrote:
| Then comes the engineering maxim, that you can only
| componentize things that have standard features and
| quality.
|
| Software engineering gets the shorter straw, because
| there's a strong force stopping standardization and pushing
| components into a single implementation. It then becomes a
| judgement of trust, not of requirements satisfaction.
| RangerScience wrote:
| I like to use SMBC's take[1] on the "Watchmaker Analogy" -
| complexity comes from, in order:
|
| (1) number of things interacting
|
| (2) complexity of interaction
|
| (3) complexity of thing
|
| So simplicity is then an inversion of that. You can
| "maximize simplicity" by:
|
| (1) minimizing the number of things
|
| (2) minimizing the complexity of interaction
|
| (3) minimizing the complexity of each thing
|
| This ends up reinventing many of things you find elsewhere
| (think SOLID; same-level-of-abstraction principle, etc)
| although I also generally find it's the first one - the
| most important one - that gets fucked up the most (one
| example: "type explosions", when you end up with just a
| bazillion different slightly different types).
|
| Also, on a broader level, there really do seem to be two
| kinds of systems: Engineered systems, which (notionally)
| attempt to minimize those things, and "evolved" systems,
| which somewhat maximize them - both economies and ecologies
| have (1) many different interacting things, (2) with
| complex interactions, and (3) which are themselves complex.
|
| You're right that it's an intuitive sense, _but_ , I do
| think the right advice and perspectives can give you a leg
| up on learning and applying that sense.
|
| [1] https://www.smbc-comics.com/?id=2344
| xiphias2 wrote:
| What's interesting in Rick Hickeys video is that he talks
| about prioritizing minimizing what each thing does over
| minimizing the number of things (that you can ignore
| anyways).
|
| Having more things doesn't make systems more complex in
| itself if they can be combined differently as
| requirements change.
| RangerScience wrote:
| I agree and disagree! That talk is a favorite - and it's
| why I say "number of _interacting_ things ".
|
| If we're weaving together three strands (basic braid),
| that's fine - we've got three interactions. If we take
| that braid and two more and weave them together, IHMO
| we're only adding three more interactions (now we're at
| 6), but if we take all nine original strands and weave
| them all together, we're up to, what... at least 72
| "interactions" (each of the 9 has an interaction with 8
| others), and that's before asking if any of the
| "interactions" themselves become "interacting things"
| (and then we get a combinatorial explosion).
|
| If instead we take those nine, and, say, braid three
| together for a bit, then swap one strand out for another,
| braid for a bit, repeat until we've gone through all nine
| - each strand is interacting with, hmm... 4 others? (two,
| then a new one, then a second new one) So then that's
| "36".
|
| It's not really a precise measurement, but I do find it
| useful question both when investigating a system, and
| when designing one: "how many things are interacting, and
| how can I reduce that?" (systemic complexity), followed
| by "how can I simplify the interactions themselves?"
| (abstraction leakage), followed by "how can I simplify
| the things?" (cleaning up well-encapsulated code).
|
| A practical example: If I want to create a test factory
| for an object, how many other related objects must I
| create for that first one to exist in a valid state?
|
| A practical application: I can get away with complexity
| in well-encapsulated code, because it's easy to come back
| to and fix; I won't have to modify anything "outside".
| But I can't get away with complexity between things,
| because then in order to come back and fix it, I have to
| deal with chunks of the entire system.
| xiphias2 wrote:
| ,,If we take that braid and two more and weave them
| together, IHMO we're only adding three more interactions
| (now we're at 6), but if we take all nine original
| strands and weave them all together, we're up to, what...
| at least 72 "interactions" (each of the 9 has an
| interaction with 8 others), and that's before asking if
| any of the "interactions" themselves become "interacting
| things" (and then we get a combinatorial explosion).''
|
| You're totally right in it.
|
| But the huge mistake I made just recently is to create a
| very simple interface that hides lots of different
| features with a few elegant flags. Although it's a super
| tiny interface that's easy to understand, the
| interactions became very complex.
|
| Instead of using my library, people started to create
| another that just does 1 thing, and can't take advantage
| of my hard work even if they wanted.
|
| Have I created 10 different totally independent
| components that use the same basic data structures (with
| a bigger total API surface), people could have used just
| the 2-3 that they need in their own system, and would
| have been able to understand (and even report / fix /
| debug) the interactions.
|
| And actually everybody wants something a bit different,
| and nobody wants really all those 9 features.
|
| This experience is what resonates with me right now when
| listening to the video.
| majkinetor wrote:
| The question is about simplicity of core implementation.
|
| Easy debuging is different goal and you can have infinity
| of such additional goals, but solution obviously can't be
| equally simple at everything at the same time (because of
| the conflict of responsilities).
| xiphias2 wrote:
| From my experience most of the complexity doesn't come from
| adding stuff (where intuition is the only thing you have,
| and this rule doesn't help), but when removing/refactoring
| stuff, or the lack of doing it.
|
| A recent known example is Elon Musk removing a lot of
| services in Twitter that were built over the years. Every
| addition probably improved the system's functionality, but
| the more complex a codebase gets, the harder it is to
| change separate pieces (by definition of complex).
|
| I believe it was a big business mistake of him buying
| Twitter (especially as Tesla is getting competitors, like
| BYD growing by 100% a year), but removing services in
| itself probably makes the code more manageble by a smaller
| team.
| p_l wrote:
| Seeing as how the service is way more buggy and
| unreliable since then...
|
| If I compared it to monkey with a wrench in server room,
| I'd be doing the monkey a disservice.
| jghn wrote:
| I always point to this talk when engineering debates around
| simplicity & complexity come up. To me the key point is that
| "simplicity" and "easy" aren't synonyms.
|
| Many people, when they said "do the simplest thing" they
| really mean "do the easiest thing". That's fine if that's
| what you want, but if you find yourself talking past someone
| else who means "do the simplest thing", that's why.
| [deleted]
| hinkley wrote:
| Obligatory Simple Made Easy link:
|
| https://www.youtube.com/watch?v=SxdOUGdseq4
|
| Simple is a matter of intuition, and that can't be transmitted
| to others easily, or with a single class or book.
|
| At one particular job we got punished by the business for
| calling things 'easy' when what we mean is that we understand
| the problem and all of the steps are (mostly) known. Our boss
| coached the hell out of us to say 'straightforward' when we
| meant 'understood', instead of using 'easy' as an antonym for
| 'quagmire' or 'scary'.
| addaon wrote:
| Agreed. But I also think that "simple to implement," "simple
| to debug," and "simple to test" are different metrics -- and
| that one has to choose which one to optimize for. This is
| independent from assessment of "simple" varying with
| intuition -- "simple" alone isn't a coherent concept.
| webnrrd2k wrote:
| And, to add a bit more nuance, simplicity can also depend
| on the stage a project is at... It may be really simple to
| implement core functionality to demonstrate an idea, but
| developing on that code can add a lot of complexity later.
| For example, adding security late in a project is almost
| always much more difficult than adding a small amount up
| front. Even the simple to implement metric can be a
| difficult judgement call.
| hinkley wrote:
| The rules of Chess aren't that hard. The rules of Go are
| even easier. You can literally spend your whole life
| unpacking the implications of the rules of either of those
| games.
|
| Ultimately both are 'too simple', resulting in a
| combinatorial explosion of states, and at least a quadratic
| expansion of consequences.
|
| We often write software to deal with consequences of
| something else. It's possible and not that uncommon for the
| new consequences to be every bit or more onerous than the
| originals. I call this role a 'sin eater' because you're
| just transferring suffering from one individual to another
| and it sounds cooler and more HR appropriate than 'whipping
| boy'.
| shagie wrote:
| That's part of the section in Programming Perl that sticks
| in my memory.
|
| From my copy...
|
| > Efficiency
|
| > ...
|
| > Note that optimizing for time may sometimes cost you in
| space or programmer efficiency (indicated by conflicting
| hints below). Them's the breaks. If program- ming was easy,
| they wouldn't need something as complicated as a human
| being to do it, now would they?
|
| > ...
|
| > Programmer Efficiency
|
| > The half-perfect program that you can run today is better
| than the fully perfect and pure program that you can run
| next month. Deal with some temporary ug- liness.1 Some of
| these are the antithesis of our advice so far.
| * Use defaults. * Use funky shortcut command-line
| switches like -a, -n, -p, -s, and -i. * Use for to
| mean foreach. * Run system commands with backticks.
| ... * Use whatever you think of first. *
| Get someone else to do the work for you by programming half
| an implementation and putting it on Github.
|
| > Maintainer Efficiency
|
| > Code that you (or your friends) are going to use and work
| on for a long time into the future deserves more attention.
| Substitute some short-term gains for much better long-term
| benefits. * Don't use defaults. *
| Use foreach to mean foreach. ...
| programd wrote:
| > Programming Perl
|
| That book is one of the most underrated and overlooked
| works on the philosophy of programming I've ever read.
| It's ostensibly about best practices in programming Perl
| (which some people consider a complex language), but in
| reality this is a very deep book about the best practices
| for programming in any language.
|
| Note the above excerpt is pretty much universally
| applicable no matter what the language. Much of the book
| is written at that level.
|
| https://www.oreilly.com/library/view/programming-
| perl-4th/97...
| hinkley wrote:
| I could say a similar thing about Practical Parallel
| Rendering. Officially it's a book about raytracing CGI in
| a cluster, but the first half of the book explains
| queuing theory and concurrency concerns in tremendous
| detail. It's a thin book to begin with, and you've more
| than gotten your money's worth if you read the first half
| and give up when they start talking about trigonometry.
| hinkley wrote:
| I've been dealing with a batch processing task that's
| written in NodeJS (partly because it was the tool at
| hand, partly because it does offline a process that can
| be done online so it's reusing code), and global
| interpreter locks are definitely introducing some new
| nuances to my already fairly broad knowledge of
| performance and concurrency. Broad not in the sense that
| I am a machine whisperer, but that I include human
| factors into this and that explodes the surface area of
| the problem, but also explains quite a lot of failure
| modes.
|
| In threaded code it's not uncommon to analyze a piece of
| data and fire off background tasks the moment you
| encounter them. But if your workload is a DAG instead of
| a tree, you don't know if the task you fired is needed
| once, twice, or for every single node. So now you
| introduce a cache (and if you're a special idiot, you
| call it Dynamic Programming which it is _fucking not_ )
| and deal with all of the complexities of that fun
| problem.
|
| But it turns out in a GIL environment, you're making a
| lot less forward progress on the overall problem than you
| think you are because now you're context switching back
| and forth between two, three, five tasks with separate
| code and data hotspots, on the same CPU rather than
| running each on separate cores. It's like the worst
| implementation of coroutines.
|
| If instead you scan the data and accumulate all the work
| to be done, and then run those tasks, and then scan the
| new data and accumulate the next bit of work to be done,
| you don't lose that much CPU or wall clock time in single
| threaded async code. What you get in the bargain though
| is a decomposition of the overall problem that makes it
| easy to spot improvements such as deduping tasks, dealing
| with backpressure, adding cache that's more orthogonal,
| and perhaps most importantly of all, debugging this giant
| pile of code.
|
| So I've been going around making code faster by making it
| slower, removing most of the 'clever' and sprinkling a
| little crypto-cleverness (when the clever thing elicits
| an 'of course' response) / wisdom on top.
| hinkley wrote:
| I am taking my own advice and re-watching this presentation.
| I'm being surprised enough by parts I don't remember that
| I've decided that I need to watch this video at least once a
| year.
|
| Certainly there are some things I've just forgotten, and
| others I just wasn't ready to hear.
| BurningFrog wrote:
| Sounds like you have an answer to your question, so I don't see
| the problem.
|
| Yeah, it'll be a project-by-project and team-by-team decision,
| and that's as it should be.
| harpiaharpyja wrote:
| The sentiment is nice but ceases to be useful when people have
| trouble distinguishing what could possibly work from what appears
| to work for a bit and then breaks down horribly.
|
| And it's not really about the fallibility of people. Often in
| engineering you can be designing in a space with a lot of
| unknowns, that simply can't be resolved without building out a
| bit to explore the space more. In such case some level of future
| proofing is warranted.
|
| I'm kind of suspicious of adages like these that assume perfect
| information.
| NegativeLatency wrote:
| Yeah sometimes you have to do the complicated thing, the saying
| "you can't build a ladder to the moon" comes to mind
|
| I do think that many people make the wrong tradeoff in terms of
| complexity to features ratio though.
| IshKebab wrote:
| Yes exactly. The simplest thing that "works" is string and duck
| tape.
| TacoSteemers wrote:
| I always look at adages like these as something to keep in mind
| for the future. We can choose the simplest thing now and make
| it easy to swap it out for the more correct and more time-
| consuming thing later.
|
| Sometimes the difficulty in distinguishing what the simplest
| thing could be comes from being in a group setting where people
| have equal say in the matter.
|
| I think everyone has personal anecdotes to support the idea of
| doing the simplest thing suitable for that moment. But how to
| convince the group? I'm not sure, I don't always succeed.
|
| A situation where I did do just the simplest thing is when I
| was asked to use project management software and a build server
| for a very early stage project with only myself as a developer.
| I declined. Instead I made a script to compile and package
| everything and emailed that to the others. We used an instant
| messenger for communication. It worked great for the early
| stage when the focus is on the MVP, though the project didn't
| go anywhere due to business reasons.
|
| It will always still be possible to use the project management
| software and build server later. But it wasn't necessary at the
| very start.
| deathanatos wrote:
| Then launch that MVP into production, and never be given an ounce
| of time by your PM to fix any of the shortcomings that you
| thought were not part of "Do the Simplest Thing". Iterate on that
| principle for new features, too: what's the simplest way to get
| this new feature out? And this one?
|
| And then find yourself surrounded by tech debt an a system that
| was cobbled together, not designed.
| int0x2e wrote:
| This is a very common case, sadly. But this is due to people
| failing to use MVPs correctly. Instead of being a tool for the
| sole purpose of rapid learning and iteration, it is used to
| falsely accelerate delivery. When done well, you build a series
| of prototypes/MVPs with the sole purpose of learning faster
| what customers really need. You should then put all your effort
| into building that really, really, well, and kill off anything
| that didn't work out. Ideally, you should always have new,
| minimalist code for new features you are exploring, and lots of
| old, extremely well designed, implemented and well-tested code
| for all the areas you already know are critical for your users
| - and nothing in between (no "nice to have" features, no failed
| experiments that linger on and contribute to your tech debt...)
|
| This takes a ton of discipline, but in my experience the only
| alternatives are to either build up a ton of tech debt, or
| build things extremely well from day 1, only to end up dying
| due to low velocity (even if you get some critical decisions
| spot on in the beginning, no PM or engineering team that I've
| ever seen has been able to make only good decisions over
| several years...).
| layer8 wrote:
| I think "simplest" needs to be applied to the whole system, not
| just to the change at hand. If you keep the system overall as
| simple as what could possibly work overall, you're probably
| already reducing tech debt. Tech debt usually implies that
| things are getting unnecessarily complicated (accidental vs.
| essential complexity).
| readthenotes1 wrote:
| I far prefer the original question "What is the simplest thing
| that could possibly work?"
|
| It is far more active than the imperative version.
|
| One might say the interrogative is the simplest thing that could
| possibly work...
| quickthrower2 wrote:
| Don't draw diagrams? Seems like not using a very valuable tool.
| Diagrams help you think and thinking can save you time in
| building the wrong thing or the wrong way. The diagram shouldn't
| take ages and pencil/paper is fine.
| blippage wrote:
| MVP: Minimal Viable Product.
|
| The greatest example of this is Unix.
|
| Multics was a huge produce that failed (initially). Bell Labs
| washed their hands of it, and didn't want anything to do with
| Operating Systems again.
|
| Ken Thompson wrote an initial scrappy version of Unix in 3 weeks.
| Re-writing to C was a tremendous move because it meant that Unix
| could be ported easily to many other systems.
|
| I heard someone say that the genius of Dennis Ritchie was that he
| knew how to get 90% of the solution using only 10% of the work.
|
| I'm working my way through Unix Haters Handbook [1], and it's a
| good read, even for someone like myself who really likes Unix.
|
| Unix and C are the ultimate computer viruses -- Lawrence Krubner
|
| [1] https://web.mit.edu/~simsong/www/ugh.pdf
| 7speter wrote:
| I thought c was primarily developed for the initial purpose of
| being the language used to write Unix and that their
| developments were practically one after the other and that
| Ritchie and Thompson were colleagues at Bell? C was designed
| for portability in mind?
| blippage wrote:
| I could be wrong, but I think Unix was originally written in
| assembler, which isn't portable.
|
| Unix first appeared on a PDP-7 (not PDP-11). PDP-7 was pretty
| old even by the standards of the time.
|
| "Originally, UNIX was written in PDP-7 assembly, and then in
| PDP-11 assembly, but then when UNIX V4 began to be re-written
| in C in 1973 and was run mostly on the PDP-11.
|
| So far as I can tell, there is no Ancient C compiler that
| targets the PDP-7, nor any provision for running UNIX V4 or
| later on the PDP-7" [0] The link also contains some other
| interesting commentary.
|
| I seem to recall that Thompson wanted to write code in
| Fortran.
|
| I'm probably getting a few details wrong. The systems were
| extraordinarily constrained, something like 4K of RAM. "++"
| exists because it was more concise that "+= 1" (although K&R
| C uses "=+ 1", I think). They really wanted to make every
| byte count.
|
| [0] https://retrocomputing.stackexchange.com/questions/6194/w
| hy-...
| IshKebab wrote:
| This is effectively meaningless (and the article even recognises
| that) because it delegates all meaning to the definition of
| "works".
|
| Even "passes all the tests" isn't a great definition. What are
| you testing?
|
| For example think about build systems. "Works" could be "builds
| everything correctly" in which case the simplest thing is just a
| shell script with all the commands written out.
|
| That's obviously terrible, so then "works" becomes "doesn't
| unnecessarily repeat work" and you end up with Make.
|
| But then Make doesn't scale to large monorepos with CI so then
| "works" becomes "and doesn't allow undeclared dependencies" and
| you come up with Bazel.
|
| So the same meaningless advice can justify wildly different
| solutions.
|
| I think better advice is just "try to keep things simple where
| possible". It's vague because it requires experience and design
| skill.
| LAC-Tech wrote:
| I agree, but I'd add in the caveat of "... in the context of a
| fleshed out bigger picture for what you're trying to solve".
|
| A lot of software lacks a clear plan. A big patchwork of local
| maxima commits that won't get you where you need to go.
|
| So I say go ahead and draw some pretty pictures. What's the
| overall vision here?
| bob1029 wrote:
| I feel like this advice works really well in some places and
| really poorly in others.
|
| I think those using safe languages and broad frameworks have a
| much greater ability to execute on "keep it simple" than those
| who use something like C and build 100% of their code in-house.
| TacoSteemers wrote:
| I think we can't avoid all difficulty, and the difficulty then
| becomes determining exactly which bits we do need.
|
| But it is a nice counter to some people's decisions to go for
| overly complex or risky (unproven?) technologies or designs.
| Xeoncross wrote:
| I wish I could convince product teams that the MVP is often just
| a single feature. Like a search bar + results page.
|
| Something we can ship very fast, then we can add the banners,
| tracking for marketing, account creation, user ratings, community
| forums, results commenting and sharing, image carousels and a
| mobile app with push notifications that the results changed. You
| know, the regular MVP stuff.
|
| So many people think agile means waterfall using sprints.
| kemiller2002 wrote:
| My voice is hoarse from saying this so many times. It's a
| constant battle trying to explain that it's not perfect, but we
| can't improve on it based on feedback, if it's not done.
| Xeoncross wrote:
| It often seems to be the illusion (confusion?) of adding
| enough features will somehow make this product useful because
| 1) I know about facebook/amazon/google and 2) it's successful
| and 3) has all the stuff.
| mynameishere wrote:
| Yes, the old days
|
| https://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.ht...
|
| "XP" almost, but not quite, became a real cult.
| joebuffalope wrote:
| The acronym should be simpler. KISS
|
| Keep It Simple Stupid
| gopisuvanam wrote:
| Old but relevant article. Figuring out the intersection of
| "simplest" and "useful" features is the trick.
| vinkelhake wrote:
| If this is applied to programming, then just be aware that "doing
| the simplest thing that can possibly work" integrated over time
| typically won't result in anything good. For any given task, the
| simplest thing that can possibly work will often have other
| effects that are hard to quantify on the spot (like increased
| tech debt).
|
| If you're working on things that are _intended_ to be short
| lived, then just do whatever is needed to get the job done and
| move on. If you 're working with something where you know there's
| a good chance it'll be around for some time, then every once in a
| while, someone will have to take on the role of saying "no, we're
| not gonna do the simplest possible thing right now".
| VBprogrammer wrote:
| Maybe. But it's often a lot easier to get from having something
| simple and working to something more complex and also working
| than it is to spend the whole time with nothing working until
| the complex part is completed.
| [deleted]
| layer8 wrote:
| See https://news.ycombinator.com/item?id=34973655 for a
| different view.
___________________________________________________________________
(page generated 2023-02-28 23:00 UTC)