[HN Gopher] Algorithms we develop software by
       ___________________________________________________________________
        
       Algorithms we develop software by
        
       Author : xal
       Score  : 243 points
       Date   : 2024-08-18 18:47 UTC (1 days ago)
        
 (HTM) web link (grantslatton.com)
 (TXT) w3m dump (grantslatton.com)
        
       | from-nibly wrote:
       | > "gun to your head, you have to finish in 24 hours, what do you
       | do?"
       | 
       | PSA: if you are a project manager / owner or some other similar
       | position you do not get to ask this. This is a personal
       | educational excercise not a way to get stuff done faster.
        
         | colechristensen wrote:
         | "gun to your head" is maybe not appropriate for work, but the
         | exercise is good for cutting to the core of a task when
         | necessary. It's really the same question as what is the minimum
         | viable product.
        
           | zug_zug wrote:
           | Yeah, I've certainly seen cases where something was overbuilt
           | and 90% of the time was wasted.
           | 
           | But I've also worked at places where things were underbuilt
           | (e.g 0 test environments whatsoever except prod). If there
           | was a gun to my head, to finish something in 1 hour, I'd test
           | in prod.
           | 
           | So I think advice that sometimes is useful, sometimes is
           | damaging, isn't really helpful. Not unless there's an easy
           | way to tell which situation is which.
        
             | phildawes wrote:
             | I think the exercise is more about exposing you to other
             | solution options (to 'break your anchoring bias'). You
             | still have to exercise judgement as to which solution is
             | right for the situation.
        
           | bckr wrote:
           | How about "building is on fire" or "company is dead
           | tomorrow"?
        
         | aidos wrote:
         | > In practice, none of the day-long plans are actually a day.
         | The gun isn't actually to your head. You can go home and sleep.
        
         | Lws803 wrote:
         | 100% this should never be an excuse to push for a faster
         | outcome. I have to admit though, as a personal mental exercise,
         | this has saved me countless of hours from going down the rabbit
         | hole of over-engineering. Some problems just need a simple
         | solution, sometimes even without any changes to code.
        
         | haliskerbas wrote:
         | at work? just shoot me then
        
         | dclowd9901 wrote:
         | So glad someone's here saying it. I am absolutely dreading
         | tomorrow morning now with the thought our manager has also read
         | this article.
        
           | athrowaway3z wrote:
           | I mistakenly read your comment as "dreading tomorrow morning
           | now that our thought-manager has also read this article"
           | which I must have subconsciously decided was inline with the
           | situation.
        
           | hn_go_brrrrr wrote:
           | Sounds like you need a different manager.
        
         | probably_wrong wrote:
         | "Here, you have a gun to your head, you have to finish in 24
         | hours. What do you do?"
         | 
         | "I set aside the slides for the pointless CEO presentation
         | tomorrow and work exclusively on this."
         | 
         | "No, you can't cancel on the CEO. Let's say you have two guns
         | to your head and 24 hours, what do you do?"
         | 
         | "I take lots of coffee, skip sleeping tonight, cancel the group
         | status meeting for Wednesday and focus on these two things."
         | 
         | "If you do that we'll look bad in front of the whole group.
         | Let's say you have three guns to your head..."
        
         | richk449 wrote:
         | Anyone have a reference to this technique? I'd like to learn
         | more.
        
       | mempko wrote:
       | "Write everything twice" is a great heuristic. Extreme
       | programming and unit tests is a dumb and wasteful technique. You
       | end up cornering yourself.
        
         | nkozyra wrote:
         | Sorry, are you saying unit testing is dumb? Not that you'd be
         | the first to say such a thing, but I've never really understood
         | this if people find them valuable. 100% test coverage is one
         | thing, but having some interdependent functions that do one
         | small thing is a perfect use case for unit tests.
        
           | mempko wrote:
           | Unit tests are a waste of time.
           | 
           | Design by Contract + system tests are a far superior
           | technique that take less time and find more bugs.
        
             | dclowd9901 wrote:
             | How do you know the contracts are being followed?
        
               | _0ffh wrote:
               | Assertions?
        
               | dataflow wrote:
               | But assertions only tell you you broke someone after the
               | fact (and only if they're enabled)? They don't do
               | anything to help prevent you from breaking them in the
               | first place.
        
               | _0ffh wrote:
               | Of course they don't, how could they? How could anything,
               | for that matter? (Apart from guarantees you could ensure
               | statically, natch.)
        
               | dataflow wrote:
               | > Of course they don't, how could they? How could
               | anything, for that matter?
               | 
               | Uh, that's literally what unit tests do? They tell you if
               | you broke any of the cases they test for, before you
               | release your implementation to other people...
        
               | _0ffh wrote:
               | Well, that's a mutual misunderstanding then. I meant
               | quite literally neither assertions nor unit tests
               | _prevent_ you from breaking things. Of course they 'll
               | help you to _catch_ those mistakes before release. I didn
               | 't think that counts as prevention, my bad. Assertions
               | should trigger during system testing if any contracts are
               | broken, so under your interpretation they _do_ prevent
               | breakage as much as units test (meaning before shipping).
        
               | dataflow wrote:
               | System tests prevent breakage _as much as_ unit tests?
               | Really?
               | 
               | How do you "system test", say, string.indexOf(string)?
               | Could you write a system test for this example to show us
               | what you mean and help us see how they're superior to
               | unit tests?
               | 
               | And how long and complicated are your system tests to
               | catch breakages "as much as" a unit test would, for this
               | example?
        
               | rocqua wrote:
               | Assertions triggering in integration tests are different
               | from unit tests. They don't involve writing mocks. They
               | are generally closer to the code, especially with design
               | by contract, so they are more likely to be fixed during a
               | refactor. They encode what you believe your code should
               | do more directly. And they can be used as a basis for
               | formal verification.
        
               | _0ffh wrote:
               | Hey, I'm arguing in favour of contracts and assertions
               | here... XD
               | 
               | I even considered formal verification, if under another
               | name.
               | 
               | Ed.
               | 
               | I think I hit a posting limit. After reading dataflow's
               | answer to gp I think I interpreted ggp differently from
               | both of you.
               | 
               | I meant quite literally neither assertions nor unit tests
               | _prevent_ you from breaking things. Of course they 'll
               | help you to _catch_ those mistakes before release. I didn
               | 't think that counts as _prevention_.
        
               | rocqua wrote:
               | Tests have the same effect right?
        
               | rocqua wrote:
               | Either through assertions, through fuzz testing, or by
               | formal verification.
        
             | sitkack wrote:
             | Unit tests are only worthwhile when your internal machinery
             | is part of the contract.
        
             | jackcviers3 wrote:
             | The last comprehensive study I read indicates that they
             | improve internal and external code quality by 76% and 88%
             | respectively while reducing productivity some[1]. If you
             | have papers that indicate your claim I'd be interested in
             | reading them or in ones that refute the metastudy linked
             | below.
             | 
             | 1. https://doi.org/10.1016/j.infsof.2016.02.004
        
               | nkozyra wrote:
               | TDD and using unit tests are not the same thing, though.
               | 
               | I'm very much a TDD sceptic, but believe unit tests have
               | a place.
        
             | dataflow wrote:
             | Confused, how do you ensure that a change to your
             | implementation of some function isn't going to break
             | clients after deployment if you don't have a unit test?
        
               | mempko wrote:
               | The client doesn't run your unit tests, but will run you
               | contracts (because contracts deploy with you software
               | while unit tests dont).
               | 
               | You might have realized users of software do things the
               | engineers don't expect, which are not covered in unit
               | tests.
        
               | dataflow wrote:
               | > The client doesn't run your unit tests
               | 
               | That's kinda the whole point... _you_ run them to catch
               | bugs and fix them so your clients never see the bugs you
               | caught in the first place.
               | 
               | > but will run you contracts (because contracts deploy
               | with you software while unit tests dont).
               | 
               | So you'd prefer your contracts to blow up your bugs in
               | your clients' faces, rather than catch bugs yourself
               | prior to releasing the code to them?!
        
               | mempko wrote:
               | You would obviously test the software before it goes to
               | the users. With contracts you would be able to have
               | information from your users that make it MUCH easier to
               | fix. Without contracts you will have a much harder time
               | fixing the bugs. Contracts catch bugs unit tests don't.
        
               | dataflow wrote:
               | > You would obviously test the software before it goes to
               | the users
               | 
               | That... is literally what unit tests do. Test the
               | software before you give it to users.
               | 
               | You seem confused what the debate is over. Nobody is
               | arguing against contracts. They're awesome. They're just
               | _not substitutes for unit tests_ (or vice versa for that
               | matter). You guys have been arguing _against unit tests_
               | , which is an absurd position to take, hence this whole
               | debate.
        
               | mempko wrote:
               | It's not absurd. Unit test are expensive and slow you
               | down while at the same time not targeting the part of
               | software where bugs occur. It's usually HOW functions are
               | composed that cause bugs, not the functions themselves.
               | Contracts rest the interaction of components while unit
               | tests don't.
        
               | dataflow wrote:
               | This is definitely absurd... but okay, riddle me this
               | then. Say you're reimplementing string.indexOf(string)
               | with your fancy new algorithm so you can deliver a nice
               | speed boost to users. How do you do your best to minimize
               | the chances of it blowing up on everyone without writing
               | unit tests?
        
               | mempko wrote:
               | First, users don't use string.indexOf(string). Users use
               | software that uses string.indexOf(string). Second, I
               | would write a test that takes generates a variety of
               | inputs to cover the domain of string.indexOf(string) and
               | have it call the old version and the new version. I would
               | then collect stats around the performance of each call
               | and make sure the new implementation is faster by the
               | threshold I meant for it to be. Since the PURPOSE OF THE
               | REFACTOR WAS PERFORMANCE. Then I would delete the test
               | after I'm satisfied it worked well on the target
               | hardware, etc.
               | 
               | Let's look at the chrome unit tests.
               | 
               | https://chromium.googlesource.com/v8/v8/+/3.0.12.1/test/m
               | jsu...
               | 
               | This test checks one case and then does a loop over to
               | make sure various sizes work. This is a POOR test because
               | it doesn't cover the domain of the function and
               | exceptional cases. This test is pointless to have and run
               | every build. Why keep it, it does nothing useful.
               | 
               | My point is that if you are refactoring a function, you
               | are going to have to write a NEW TEST anyway because the
               | purpose of a refactor is different each time. The old
               | tests are going to be useless. This is why contracts are
               | so useful because they will ALERT YOU when the software
               | does something you didn't assume. Unit tests don't do
               | this.
               | 
               | From an information theory perspective, the old tests
               | would not provide you with new information. If you want
               | to make sure your refactor works like the old function,
               | then compare the outputs of your new function with the
               | old one over the domain of the function. Then if it's
               | good, delete the tests because why keep them.
               | 
               | Experience shows that users will do things to your
               | program you did NOT expect and therefore your tests will
               | not cover. And more likely than not, refactoring requires
               | rewriting tests anyway so the old tests are usually
               | always useless.
               | 
               | Now SYSTEM tests ARE useful. Tests that wire up many
               | components and test them are useful. But a UNIT test,
               | which tests one function is often just a waste of time to
               | keep.
        
               | dataflow wrote:
               | Honestly... I can see it's going to be genuinely
               | exhausting for me to rebut point-by-point here, so I'll
               | just let others read this and continue if they're
               | interested. I really appreciate the response though, at
               | least it explains your thought process well.
               | 
               | I have one question for you that I feel I have to ask:
               | have you actually practiced commercial software
               | development on a team (say, 5+ developers on the same
               | codebase) in this manner that you describe for a
               | significant period of time (say, 2+ years)? and if so, do
               | you feel the resulting software has been robust and
               | successful?
        
               | mempko wrote:
               | I've been doing this style of software development for 16
               | years (out of 28 years programming) across various
               | projects.
               | 
               | If you want a small project that I wrote to look at, see
               | henhouse https://github.com/mempko/henhouse. I wrote an
               | article talking about design by contract and why it's
               | better than TDD here
               | https://mempko.wordpress.com/2016/08/23/the-fox-in-the-
               | henho...
               | 
               | I've built a computer vision system that processed
               | petabytes of data with only one or two bugs in production
               | for any given year. At any given time we kept a bug list
               | of zero. For the last five years I built a trading system
               | using this same process. Again, we don't keep a bug list
               | because if there were bugs, the system wouldn't even run.
               | And if there is a bug we have to fix it immediately. We
               | do have tests, but they are system tests. The worst bug
               | we had that took too long to catch was in a part of the
               | system that DIDN'T use contracts.
               | 
               | Design by Contract is a secret weapon people don't seem
               | to know about.
               | 
               | Also see https://github.com/mempko/firestr, which I used
               | Design by Contract extensively. It's a GUI program so the
               | user can do crazy things.
               | 
               | Learn Design by Contract. Do system testing. Do
               | exploratory testing. Do fuzz testing. Keep a bug list of
               | zero. Don't waste time on unit testing.
               | 
               | If you are looking for popular software built using
               | Design by Contract to various degree.
               | 
               | See SQLite (uses assertions heavily), .NET framework from
               | Microsoft, Many of the C++ Boost libraries, Parts of
               | Rust, Parts of Qt. The Vala programming language, Ada
               | GNAT... and many others.
               | 
               | Here is a research paper from Microsoft that shows the
               | advantage of contracts and code quality.
               | https://www.microsoft.com/en-us/research/wp-
               | content/uploads/...
        
               | dataflow wrote:
               | I feel there's something missing in what you describe,
               | and I'm trying to pinpoint what it is...
               | 
               | I can see it working if you have very few developers
               | touching each piece of code, or if you get to exert
               | control over the final application. But I don't see how
               | it can work for large codebases or teams over long
               | periods of time (read: large businesses)... especially
               | not for library development, where your team is only
               | responsible for providing library functionality (like
               | string.indexOf(string) in my example, or matrix
               | multiplication, or regexes, or whatever libraries do) and
               | you don't necessarily even know whom the users are. There
               | is no "system" or "integration" at that point, you're
               | just developing one layer of code there, which is the
               | library -- a piece of code responsible for doing just one
               | thing. How the heck do you make sure arbitrary team
               | members touching code don't end up introducing silly bugs
               | over time, if not with unit tests?
               | 
               | Have you built any commercial _libraries_ in this manner,
               | rather than applications? i.e. where everyone on your
               | team is jointly responsible for your library 's
               | development (like the implementation of
               | string.indexOf(string) in my example), and other folks
               | (whether inside or outside the company) are the ones who
               | piece together the libraries to create their final
               | application(s)?
        
               | mempko wrote:
               | I updated my original post with examples. I also included
               | this research paper from Microsoft that shows a clear
               | advantage of contracts and code quality.
               | https://www.microsoft.com/en-us/research/wp-
               | content/uploads/...
               | 
               | Note also types are a contract. TypeScript is basically
               | introducing contracts at a high level to javascript.
        
               | dataflow wrote:
               | > I updated my original post with examples.
               | 
               | Awesome, I'll dissect them and show you exactly where
               | you're drawing the wrong conclusion ;)
               | 
               | > I wrote an article talking about design by contract and
               | why it's better than TDD here
               | 
               | Nobody is advocating for TDD or disagreeing with that.
               | Having unit tests != TDD.
               | 
               | > https://github.com/mempko/henhouse
               | 
               | So far as I can see, you're literally the _only_
               | developer here -- which exactly illustrates my point. You
               | can ignore a LOT of good engineering practices and be
               | sloppy about a ton of things if you 're the only
               | developer (or one of a handful of developers), because
               | hardly anything ever changes underneath you or without
               | your knowledge. (Source: I've done it too.)
               | 
               | > See SQLite (uses assertions heavily)
               | 
               | SQLite has like... 3 developers? The vast majority,
               | again, being 1 person. (I didn't even bother verifying
               | your claim that they don't have unit tests, FWIW.)
               | 
               | > .NET framework from Microsoft
               | 
               | .NET absolutely has unit tests, here's one example: https
               | ://github.com/dotnet/runtime/blob/ebabdf94973a90b833925..
               | .
               | 
               | > Many of the C++ Boost libraries
               | 
               | All the ones I recall ever seeing have unit tests...
               | which "many" don't? Here's one that does: https://github.
               | com/boostorg/regex/blob/develop/test/regress/...
               | 
               | > Parts of Rust
               | 
               | Again, you're gonna have to cite what you're talking
               | about because Rust definitely has unit tests:
               | https://github.com/rust-
               | lang/rust/blob/master/library/core/t...
               | 
               | > Parts of Qt. The Vala programming language, Ada GNAT...
               | and many others.
               | 
               | I'm not gonna keep digging up their unit tests, you
               | (hopefully) get the point above.
               | 
               | > I also included this research paper from Microsoft that
               | shows a clear advantage of contracts and code quality
               | 
               | As I said above, _nobody is arguing against contracts_! A
               | paper showing they 're awesome doesn't mean they're
               | substitutes for unit tests in every situation. Your paper
               | only mentions the phrase "unit test" twice, and neither
               | of them is saying DbC substitutes for them.
        
               | mempko wrote:
               | Replying here to your last post here because HN won't let
               | me reply to it (maybe too nested?). You say nobody is
               | arguing against contracts.
               | 
               | > So you'd prefer your contracts to blow up your bugs in
               | your clients' faces, rather than catch bugs yourself
               | prior to releasing the code to them?!
               | 
               | That's you arguing against contracts. Contracts need to
               | blow up when users use the software (including you and
               | your testers before you ship). You should ship if you
               | find no contracts blowing up. But you need to let them
               | blow up in user faces too. They provide valuable
               | information AFTER SHIPPING. Otherwise they lose a lot of
               | their value.
               | 
               | Saying contracts shouldn't run in shipped code misses the
               | whole point about what contracts are.
               | 
               | > That... is literally what unit tests do. Test the
               | software before you give it to users.
               | 
               | No, unit tests test a portion of the software before
               | shipping. My argument is they aren't worth the cost and
               | provide little value. Most of the value comes from SYSTEM
               | tests, integration tests, exploratory testing, fuzz
               | testing, etc. Unit tests are the weakest form of testing.
               | 
               | Here is a great argument against them called Why Most
               | Unit Testing is Waste by Coplien. It's a dense argument
               | which I agree with.
               | 
               | https://wikileaks.org/ciav7p1/cms/files/Why-Most-Unit-
               | Testin...
        
               | dataflow wrote:
               | >> So you'd prefer your contracts to blow up your bugs in
               | your clients' faces, rather than catch bugs yourself
               | prior to releasing the code to them?!
               | 
               | > That's you arguing against contracts.
               | 
               | No. Notice what I wrote earlier? Where I very
               | specifically said "contracts are awesome _but not
               | substitutes for unit tests_ "?
               | 
               | That's exactly the same thing I was saying here. I was
               | arguing against _relying on contracts to catch the bugs
               | unit tests would 've caught_. _Nobody was ever telling
               | you to avoid contracts anywhere._ Like I said, _they 're
               | awesome_, and both are valuable. I'm just saying they
               | don't substitute for your unit tests. Just like how
               | screwdrivers don't substitute for hammers, as awesome as
               | both are.
               | 
               | > Saying contracts shouldn't run in shipped code misses
               | the whole point about what contracts are.
               | 
               | I _never_ said that, you 're putting words in my mouth.
               | 
               | > No, unit tests test a portion of the software before
               | shipping. My argument is they aren't worth the cost and
               | provide little value. [...]
               | 
               | I just gave you a detailed, point-by-point explanation of
               | what you've been missing in the other thread with your
               | _own_ purported counterexamples:
               | https://news.ycombinator.com/item?id=41287473
               | 
               | Repeating your stance doesn't make it more correct.
        
               | spc476 wrote:
               | I'm not mempko, but I can answer that question---yes. For
               | over a decade on the same code base with a team that
               | ranged from 3 to 7 over the years. We did have what would
               | be considered end-to-end tests, or maybe integration
               | tests that tested the entire system from ingress
               | (requests coming in) to egress (results going out) that
               | ensured the existing "business logic" didn't break.
               | 
               | There were no unit tests, as a) the code wasn't written
               | in a style to be "unit" tested, and b) what the @#$@Q#$
               | is a unit anyway? Individual functions in the code base
               | (a mixture of C89, C99, C++98 and C++03) more or less
               | enforced "design by contract" by using calls to assert()
               | to assert various conditions in the code base. That
               | caught bugs as it prevented the wrong use of the code
               | when modifying it.
               | 
               | Things only got worse when new management (we were bought
               | out) came in, and started enforcing tests to the point
               | where I swear upper management believed that tests were
               | more important than the product itself. Oh, the bug count
               | shot up, deployments got worse, and we went from
               | "favorite vendor" to "WTF is up with that vendor?" within
               | a year.
        
               | dataflow wrote:
               | Thanks for the reply. See my reply here:
               | https://news.ycombinator.com/item?id=41287310
               | 
               | It sounds like you, too, were doing application
               | development rather than library development. By which I
               | mean that -- even if you were developing a "library" --
               | you more or less knew where & how that library was going
               | be used in the overall system/application.
               | 
               | That's all fine and dandy for your case, but not all
               | software development has the luxury of being so limited
               | in scope. Testing the application fundamentally misses a
               | lot more edge cases than a unit test would ever miss. And
               | setup/teardown takes so much longer when every single
               | change in some part of the codebase requires you to re-
               | test the entire application.
               | 
               | When your project gets bigger or the scope becomes open-
               | ended (think: you're writing a library for arbitrary
               | users, like Boost.Regex), you literally have no
               | application or higher-level code to test the
               | "integration" against -- unit tests are your only option.
               | How else are you going to test something like
               | regex_match?
               | 
               | > what the @#$@Q#$ is a unit anyway?
               | 
               | https://res.cloudinary.com/practicaldev/image/fetch/s--
               | S_Bl5...
               | 
               | P.S. I have to also wonder, how much bigger was the
               | entire engineering team compared to the 3-7 people you
               | mention? And if it was significantly bigger, how often
               | were they allowed to make changes to your team's code? It
               | seems to me you probably tight control over your code and
               | it didn't see much flux from other engineers. Which,
               | again, is quite a luxury and not scalable.
        
               | spc476 wrote:
               | I learned early on to automate the test system. It went
               | from a 30-minute setup to run a 5-hour test (which I
               | wrote) to one command that took maybe a minute to run all
               | tests (which I also wrote, and by the end, you could
               | specify just what tests you wanted to run). And yes, that
               | one command generated all the test data and ran all the
               | processes required to test.
               | 
               | Towards the end, management was asking to test for
               | negatives ("Write tests to make sure that component T
               | doesn't get a request when it isn't supposed to," when
               | component T was a networked component that queried a DB
               | not under our control). Oh, and our main business logic
               | made concurrent requests to two different DBs and again,
               | I had to write code to test all possible combinations of
               | replies, timeouts and dropped traffic to ensure we did
               | The Right Thing. Not an easy thing to unit test, as the
               | picture you linked to elegantly showed (and, you side
               | stepped my question I see).
               | 
               | The entire engineering team for the project was maybe 20,
               | 25 people, but each team (five total) had full control
               | over their particular realm, but all were required for
               | the project as a whole. Our team did C and C++ on
               | Solaris; three teams used Java (one for Android, and two
               | on the server side) and the final team did the whole
               | Javascript/HTML/CSS thang.
               | 
               | You're right that we didn't see much flux from the other
               | teams, nor from our customer (singular---one of the
               | Oligarchic Cell Phone Companies), but that's because the
               | Oligarchic Cell Phone Company doesn't move fast, nor did
               | any of the other teams want do deal with phone call flows
               | (our code was connected to the Phone Network). We perhaps
               | saw the least churn over the decade simply due to being
               | part of the Phone Network---certainly the other teams had
               | to deal with more churn than us (especially the Android
               | and JS/HTML teams).
               | 
               | Also, each team (until new management took over) handled
               | deveopment differently; some teams used Agile, some
               | scrum, some none. Each team had control. Until we didn't.
               | And then things fell apart.
               | 
               | If I was developing a library, the only tests I might
               | have would be to test the public API and nothing more. No
               | testing of private (or internal) code as that would
               | possibly churn too much to be useful. Also, as bugs are
               | discovered, I would probably keep the code that proves
               | the error to prevent further regressions if the API
               | doesn't change.
               | 
               | One thing I did learn at that job is never underestimate
               | what crap will be sent your way. I thought that the
               | Oligarchic Cell Phone Company would send good data; yes
               | for SS7 (the old telephony protocol stack), but not at
               | all for SIP (the new, shiny protocol for the Intarweb
               | age).
        
               | sham1 wrote:
               | To be fair, "functions themselves" seldom form a valid
               | unit, so in practice you'd end up having to test the
               | composition of said functions.
        
         | gavmor wrote:
         | "Write everything twice" is sometimes called a "spike."[0]
         | 
         | > A spike is a product development method originating from
         | _extreme programming_ that uses the simplest possible program
         | to explore potential solutions.
         | 
         | In my career, I have often _spiked_ a solution, thrown it away,
         | and then written a test to drive out a worthy implementation.
         | 
         | 0. https://en.wikipedia.org/wiki/Spike_(software_development)
        
       | nkozyra wrote:
       | Write everything (generally, new features) twice has turned out
       | to be really good strategy for me, but it doesn't sit well with
       | bizdev or project managers and tends to be perceived as
       | unnecessary slowness.
       | 
       | But if you plow through a feature and get it "working," you'll do
       | much of that work cleaning up the logic and refactoring through
       | your first pass. What rewriting allows you to do is crystalize
       | the logic flow you developed the first time and start cherry-
       | picking in a more linear fashion to meet the blueprint. It also
       | tends to reduce the urge (/ need) for larger scale refactorings
       | later on.
        
         | andsoitis wrote:
         | A project manager or bizdev person writes, rewrites, and
         | rewrites again the document they produce do they not? Or do
         | they write the perfect document at first go?
        
           | stanac wrote:
           | Worst kind of jira ticket is just a link to a document that
           | can be edited anytime. In that case I just replace the link
           | with a new link pointing to the fixed version of the document
           | and inform the author of the ticket/document about it.
        
             | throwaway87483 wrote:
             | Depending on what kind of document it is, I often resort to
             | extracting its contents with pandoc by converting it into
             | markdown, and then replacing the original description.
             | Makes search work properly too.
        
           | bdw5204 wrote:
           | If I'm writing something, I'm writing it once. That
           | "prewriting" stuff they teach in schools just slows down the
           | process and makes you overthink your choice of words. I take
           | the same "1 take" approach with code with the idea being to
           | write the best solution on the first try. Why waste time
           | writing something bad just so you can fix it later? That
           | doesn't make any sense.
           | 
           | As I'm writing, I do go back and make changes as they pop
           | into my head. But once I'm done writing it, I'm done unless I
           | notice an obvious mistake after the fact.
        
             | bckr wrote:
             | 1. You don't take any notes or make any bullet points?
             | 
             | 2. > As I'm writing, I do go back and make changes as they
             | pop into my head
             | 
             | This contradicts the idea that you only write once.
             | 
             | 3. You don't get feedback on your first finished version
             | and make changes?
        
             | kccqzy wrote:
             | Don't think of the first iteration as "prewriting" and
             | instead think of the subsequent iteration as "editing."
        
         | dclowd9901 wrote:
         | How would they know? Are they monitoring your code writing?
        
           | actionfromafar wrote:
           | Depending on how the dev environment is setup, yes. Maybe you
           | need something to go through a CI/CD pipeline. If you can't
           | test it on your local machine, it can easily be visible to
           | many people.
        
         | lylejantzi3rd wrote:
         | > it doesn't sit well with bizdev or project managers
         | 
         | To be fair, it makes everything twice as expensive. Managers
         | are always going to reflexively push back against that, even if
         | the new feature covers that cost and more.
        
           | edflsafoiewq wrote:
           | The second time doesn't cost as much as the first.
        
             | jrvarela56 wrote:
             | And the first is cheaper than a 'regular single version' bc
             | you build it with the thought that you will throw it away.
        
               | nkozyra wrote:
               | You throw it away but in truth much of it survives in a
               | much better design.
        
           | richk449 wrote:
           | > To be fair, it makes everything twice as expensive.
           | 
           | The article argues it makes it less expensive to reach any
           | specific quality level (above some threshold).
           | 
           | The threshold isn't really addressed in the article, but it
           | is implied that for any realistic quality need, the write
           | twice approach will be cheaper.
           | 
           | To conclude it makes everything twice as expensive, you have
           | to ignore any cost except the initial write. That's not
           | realistic.
        
           | ozim wrote:
           | What hits hard is realizing that most features are not worth
           | it. They just shouldn't be developed.
           | 
           | Unfortunately biznes wants features and more of them and if
           | possible for free.
        
             | kmoser wrote:
             | I find half my job as a developer is writing code, and the
             | other half is advising clients on which features _not_ to
             | implement.
        
           | euroderf wrote:
           | From the article:
           | 
           | > Rewriting the solution only took 25% the time as the
           | initial implementation
           | 
           | Seems reasonable.
        
             | lylejantzi3rd wrote:
             | > Seems reasonable.
             | 
             | Not to the manager, which is the point, not how long it
             | takes to rewrite it.
        
         | pjbster wrote:
         | > Write everything (generally, new features) twice has turned
         | out to be really good strategy for me, but it doesn't sit well
         | with bizdev or project managers and tends to be perceived as
         | unnecessary slowness.
         | 
         | Silo-isation compounds this. If the maintenance costs are borne
         | by another team or if any rework will be funded out of a
         | different project, the managers are not going to care about
         | quality beyond the basic "signed off by uat".
        
         | eschneider wrote:
         | I spent some time doing consulting with an engineering manager
         | who would keep requesting different (correct) implementations
         | of the same functionality until had seen enough and then he'd
         | pick one. This did lead to some high quality software for what
         | needed to be a high reliability product.
         | 
         | I should probably mention that I was doing consulting
         | engineering here because no employees work work for the guy...
        
       | jesse__ wrote:
       | This is one of the best "programming advice" posts I've ever
       | read, right up there with the grug brained developer.
        
         | 201984 wrote:
         | Not sure why this was downvoted?
        
           | jesse__ wrote:
           | Surprised me too..
        
             | gamegoblin wrote:
             | I appreciated the comment (author here)
        
         | BoiledCabbage wrote:
         | Likely most people don't know what you're referring to and
         | assumed you thought the advice was bad.
        
         | halfcat wrote:
         | https://grugbrain.dev/ for those not familiar, by the creator
         | of HTMX
        
       | a1o wrote:
       | > Write everything twice
       | 
       | There's an enhancement in a software I use/maintain that I wrote
       | once and lost (the PC I wrote kaput and I was writing offline so
       | I also didn't backup). It was an entire weekend of coding that I
       | got very in the zone and happily coded.
       | 
       | After I lost that piece of code I never could get the will to
       | write that code again. Whenever I try to start that specific
       | enhancement I get distracted and can't focus because I also can't
       | remember the approach I took to get that working and get lazy to
       | figure it out again how that was done. It's been two years now.
        
         | mgaunard wrote:
         | That's a good point. Particularly good pieces of work are hard
         | to rewrite.
         | 
         | I remember rewriting some piece of infrastructure once when I
         | moved to another job, but I failed to summon the energy to
         | rewrite it a second time at another job.
        
           | AlotOfReading wrote:
           | Every time I've pushed through that feeling and rewritten it
           | anyway, the end result was better than the original. The
           | memories eventually come back once I get into the problem and
           | hindsight makes clear how much stuff past-me missed.
        
             | HappMacDonald wrote:
             | Especially in cases where its a project that got derailed
             | or interrupted and I have to start over, the biggest
             | problem for me is inability to concentrate the second time
             | largely from overwhelming and vertiginous deja vu.
             | 
             | Namely, at any given moment my memories of doing the same
             | thing before interfere with my current reality of trying to
             | do it again like intrusive thought microphone feedback.
        
       | Etheryte wrote:
       | I really like the footnote that indirectly says that sometimes
       | you just need to spin up a background thread to figure something
       | out. Resonates heavily with my experience, to the point where I
       | feel like a lot of the value my experience brings is identifying
       | this class of problems faster. You stumble onto it, recognize
       | it's the think about it passively type and move on to other
       | things in the meanwhile. It would be easy to bang your head on it
       | and get nowhere, sometimes you just need to let it sit for a bit.
        
       | mgaunard wrote:
       | Most software has a finite lifetime of a few years. You rewrite
       | everything eventually.
       | 
       | What you should be worried about is the code that hasn't been
       | rewritten in ten years.
        
         | spc476 wrote:
         | My blogging engine [1] is almost 25 years old now. Have I
         | rewritten it? If by "rewritten" you mean "from scratch", then
         | no. I haven't. It _has_ , however, seen several serious
         | workings and refactorings over the years (the last great one
         | was the removal of _all_ global variables [2] a few years ago).
         | Starting over would have been just too much work.
         | 
         | [1] https://github.com/spc476/mod_blog
         | 
         | [2] As therapy for stuff going on at work.
        
         | snapcaster wrote:
         | Weird, i would actually have the opposite conclusion. Can you
         | say more?
         | 
         | >What you should be worried about is the code that hasn't been
         | rewritten in ten years.
         | 
         | Why would I worry? it's been running for 10 years without
         | significant changes. Isn't that a sign it's more or less
         | accomplishing its purpose?
        
           | HappMacDonald wrote:
           | Well, there's bitrot.
           | 
           | Needs shift. Expectations shift. The foundations that the
           | code relies upon shift.
           | 
           | And familiarity with how things actually work inside of the
           | black box evaporates leaving things distressingly fragile
           | when the foundation finally gives way.
           | 
           | It's like when an old dam has "stood the test of time". More
           | and more people (and business practices) wind up naively
           | circle their wagons around presuming it will remain in
           | operation forever and the consequences of what will happen
           | when it finally does fail add up faster than unchecked credit
           | card debt.
        
       | justinl33 wrote:
       | > start over each day This reminds me of "spaced repetition" in
       | learning theory. Drilling the same problem from scratch is a
       | great way to get better at iterating through your rolodex of
       | mental models, but so many people prioritize breadth because they
       | think it is the only way to generalize to new problems.
        
       | rmnclmnt wrote:
       | > Write everything twice
       | 
       | I'd say << Write everything three times >> because it usually
       | take 3 versions to get it right: first is under-engineered,
       | second is over-engineered and third is hopefully just-right-
       | engineering
        
         | passion__desire wrote:
         | Damped oscillation, approaching the right value?
        
       | steve918 wrote:
       | I like the "gun to the head" heuristic but I would probably
       | rephrase it to be something like "If you only had 24hrs to solve
       | this or the world would come to an end".
        
       | hintymad wrote:
       | I remember seeing somewhere a popular list of top 10 algorithms
       | used in systems, and it's kinda depressing to realize that the
       | most recent algorithm on the list, Skip List, was invented
       | roughly 30 years ago, and every single one of them was taught in
       | an introductory data structure course. That is, we most likely do
       | not need to study the internals of algorithms nor need to
       | implement them in production. For such a long time in history,
       | smart and selfless engineers already encapsulated the algorithms
       | into well abstracted and highly optimized libraries and
       | frameworks.
       | 
       | Of course, there are exceptions. ClickHouse implemented dozens of
       | variations of HashTable just to squeeze out as much performance
       | as possible. The algorithms used in ClickHouse came from many
       | recent papers that are heavy and deep on math, which few people
       | could even understand. That said, that's just exception instead
       | of norm.
       | 
       | Don't get me wrong. Having a stable list of algorithms is
       | arguably a hallmark of modern civilization and everyone benefits
       | from it. It's just that I started studying CS in the early 2000s,
       | and at that time we still studied Knuth because knowing
       | algorithms in-depth was still a core advantage to ordinary
       | programmers like me.
        
         | smusamashah wrote:
         | Did you read the article?
        
           | hintymad wrote:
           | You're right. I rushed and assumed. Thanks
        
       | layer8 wrote:
       | This reminds me of https://ntietz.com/blog/throw-away-your-first-
       | draft/, previously discussed in
       | https://news.ycombinator.com/item?id=37003910.
        
       | pkoird wrote:
       | A good code, in my opinion, is written by appropriate selection
       | of suitably contained abstractions. The problem with this, and
       | the article does try to talk about it, is that for you to select
       | appropriate abstractions, you need to know the "entire" thing.
       | Which is to say, you need to have a knowledge of something that
       | isn't there yet.
       | 
       | In other engineering disciplines like say civil or architecture,
       | this problem is solved by using a good blueprinting paradigm like
       | CAD layouts, but I find a distinct lack of this in software[1].
       | Ergo this advice which is a rephrasing of "know first and build
       | later". But it is also equally easy to lose oneself in what's
       | called an analysis paralysis i.e. get stuck in finding the best
       | design instead of implementing a modest one. In the end, this is
       | what experience brings to table I suppose, balance.
       | 
       | [1]closest I can think of are various design diagrams like the
       | class diagrams etc.
        
       | ww520 wrote:
       | I usually won't rewrite the whole thing twice, but would rewrite
       | parts of it multiple times. For the very least, the second time
       | around I would format things and add comments to make things
       | easier to be understood. Code should be written for
       | comprehension.
        
       | halfcat wrote:
       | Dan Abramov talks about WET (write everything twice) [1] as
       | generally a good approach, primarily because you often don't know
       | the right abstraction up front, and a wrong abstraction is way
       | worse than a copy/paste.
       | 
       | He has some good visuals that illustrate how incorrectly
       | dependent and impossible to unwind wrong abstractions can become.
       | 
       | [1] https://youtu.be/17KCHwOwgms
        
       | aleph_minus_one wrote:
       | > Another heuristic I've used is to ask someone to come up with a
       | solution to a problem. Maybe they say it'll take 4 weeks to
       | implement. Then I say "gun to your head, you have to finish in 24
       | hours, what do you do?"
       | 
       | Pretend to be capable of doing this, and in the short moment
       | where the other person is not attentive, get the gun and kill
       | him/her. This satisfies the stated criteria:
       | 
       | > The purpose here is to break their frame and their anchoring
       | bias. If you've just said something will take a month, doing it
       | in a day must require a radically different solution.
       | 
       | > The purpose of the thought experiment isn't to generate the
       | _real_ solution.
       | 
       | :-)
       | 
       | ---
       | 
       | Lesson learned from this: if you can't solve the problem that the
       | manager asks you for, a solution is to kill the manager (of
       | course you should plan this murder carefully so that you don't
       | become a suspect).
       | 
       | :-) :-) :-)
        
       | vanjajaja1 wrote:
       | > If, after a few days, you can't actually implement the feature,
       | think of what groundwork, infrastructure, or refactoring would
       | need to be done to enable it. Use this method to implement that,
       | then come back to the feature
       | 
       | really good, this is key. building a 'vocabulary' of tools and
       | sticking to it will keep your velocity high. many big techs lose
       | momentum because they dont
        
         | physicles wrote:
         | Agreed. I've also heard this stated as:
         | 
         | > for each desired change, make the change easy (warning: this
         | may be hard), then make the easy change"
         | 
         | (earliest source I could find is @KentBeck on X)
         | 
         | I love the idea of that vocabulary of tools and libraries, too.
         | I strongly resist attempts to add to or complicate it
         | unnecessarily.
        
       | simpaticoder wrote:
       | Very interesting suggestions, all worth trying. Having a very
       | capable coworker can help here, because they can show you what
       | can be done in a short amount of time. Specifically I've noticed
       | that some devs get "winded" by a change and want to take a break
       | before moving on; others simply continue. This ability can be
       | improved with practice, both within and across contexts. Doing
       | things quickly is valuable for many intrinsic reasons that are
       | often overlooked because we descry the poor extrinsic reasons. As
       | with car repair, the odds that you forget how to reassemble the
       | car scales with the time the repair takes. Similarly, if you can
       | execute a feature in a day (especially a complex one that
       | requires changes to many parts of a repo, and/or more than one
       | repo) this is much less risky than taking many days or weeks. (To
       | get there requires that you have firm command of your toolset in
       | the same way a mechanic understands his tools, or a musician
       | understands her instrument. It also requires that externalities
       | be systematically smooth - I'm thinking particularly of a
       | reliable, locally repeatable, fast CI/CD process.)
       | 
       | (The calculus here is a little different when you are doing
       | something truly novel, as long periods of downtime are required
       | for your brain to understand how the solution and the boundary
       | conditions affect each other. But for creating variations of a
       | known solution to known boundary conditions, speed is essential.)
        
       | DrScientist wrote:
       | I find the follow approach quite useful.
       | 
       | 1. First write down a bunch of idea of how I might tackle the
       | problem - includes lists of stuff that I might need to find out.
       | 
       | 2. Look at ways I break the task down to 'complete-able in a
       | session'.
       | 
       | 3. Implement, in a way the code is always 'working' at the end of
       | session.
       | 
       | 4. Always do a brain dump into a comment/readme at the end of the
       | session - to make it easy to get going again.
        
       | gregors wrote:
       | "you have 24 hrs" and "write everything twice" ......they go hand
       | in hand don't they? You're definitely going to rewrite it if you
       | slap code out there.
        
       ___________________________________________________________________
       (page generated 2024-08-19 23:02 UTC)