• dahdum 2 days ago

    > They end-up making there managers happy, yet in the long-run everybody is panicking and they are considering refactoring or even building the application from scratch after 4-5 years.

    As mostly a startup dev I’ve never worked in a company with a runway long enough to afford worrying about a potential rewrite 5 years in the future. I’ve had to rewrite some of the most spaghetti founder code ever, but surviving long enough to do so was a sign of success.

    Author isn’t wrong per se, but code purity isn’t always a worthwhile goal, and needs to be balanced by the needs of the business. Virtually all of the code I’ve written over the years has been tossed by acquiring companies moving everything to “their stack”, acquihire, company shutting down, product pivots, or better 3rd party software becoming available/affordable. I’ve pushed some trash tier code over the years because it worked just well enough to drive growth/revenue and keep the lights on.

    • haswell 2 days ago

      > I’ve pushed some trash tier code over the years because it worked just well enough to drive growth/revenue

      With all respect, this summarizes everything I’ve come to hate about our industry over the years.

      I understand why this happens, and I’ve also been the person churning out crappy code at points in my career. But I think it also highlights how backwards the incentives have become, and we’re constantly seeing the real world impact playing out as the next zero day, the next botnet, the next Boeing scandal, etc.

      I’m not saying there’s never a place for bad-but-working code, but I’m increasingly convinced it never belongs in customer facing products, and that we have a major task ahead of us collectively to correct the mindset behind this and fix the incentive structure that enables this.

      Software runs the world now, and a frighteningly large number of software companies do not take their position of power seriously.

      • fabian2k 2 days ago

        One big problem is that you often don't know yet what you actually need, you only find that out when your software is in front of real users. So the later versions might be substantially different than your MVP. Building a very robust first version might be entirely useless if you have to throw away most of it after discovering it doesn't actually solve the user's needs.

        • haswell 2 days ago

          The issue is that what often happens next is the thing that got cobbled together as a customer POC ends up in production.

          Most hardware goes through extensive validation and revision before tooling to manufacture and ship at scale. The software space hasn’t always (often has not) found the correct balance between low cost early iterations and a properly hardened customer-ready product. The temptation is strong to just call it ready because it’s always possible to patch it later.

          While I agree that finding this balance is a challenge, I don’t think that lowers the criticality of productionizing the code or the risk of using these early stage products that haven’t “grown up”.

          • rekabis 17 hours ago

            > So the later versions might be substantially different than your MVP. Building a very robust first version might be entirely useless if you have to throw away most of it after discovering it doesn't actually solve the user's needs.

            IME, the core foundation of the product should be built such that no more than ≈20% or so of the MVP is ejectable in this manner. Not that it can’t, but more importantly: that it doesn’t have to. An MVP should be so basic that the majority of it would be foundational to anything being built, and so would remain in part or in whole no matter what redirection is taken.

            This is not always possible, but for most ideas there is a core element that you can start with, even if usefulness won’t really be there without a lot more functionality.

            > you often don't know yet what you actually need, you only find that out when your software is in front of real users.

            Which is why an MVP should only ever be the absolute minimum viable product - so that as soon as it ends up in front of users, you can lurk in whatever user forum you stand up and advertise for the product (subreddit, etc.) and listen to what the users are saying. Some of them may inadvertently drop ideas that can make or break your product, and it’ll be things you never thought of. Being able to pivot on a dime is why an MVP is so vital to begin with.

          • mihaaly 2 days ago

            Those shipping fast and lot write software not to use but to sell. Not for the user but for sales and marketing departments. And this is why software and programmers are not respected, rightfully so. Judged by their products. And software are crap (and then reasoned with vigour why crap is good by those having incentives in it). Much more time than not, the not is the exception nowadays.

            Those having too little resources (money) for their monumental ambition also ship fast.

            Also it is so f annoying. All those river of notifications about 'hey, brend new version, now!, stop everything and download right away or else!' is a great nuisance. Like if this was the center of the life of the user, to have the newest and prettiest and greatest new feature (or mostly fixup of f*ups) of the software used. Secret for developers: no one cares. They need a tool to do the thing, and that's it. Do it well, do it smooth, that's all that counts. Not the new versions. Please write it well in the first place instead of this endless tinkering and bugging the customer.

            Sipping too fast is some sort of premature ejaculation of the programmers' mind.

            • dyauspitr 2 days ago

              Well most places putting out code for the first time don’t have the luxury of spending the time to put out perfect code. The funding only lasts so long, you’re trying to outpace competitors, you end up getting continuous scope creep etc. Star Citizen is a great example of what happens when you want to get everything perfect before you release it, by the time you’re done someone else has eaten your lunch.

              • bschmidt1 2 days ago

                Is code more like poetry or more like a recipe? If the former, then yes we should be allowed the time and space to craft the highest syntactic art imaginable. But if it's the latter, it should just be quick, correct, readable, and extensible.

                If it's art - how dare you ruin my masterpiece?

                If it's business - we had a solution deployed for the customer in less than an hour.

                If syntax (poetry) is your #1 take your time. If money is your #1 you wouldn't call it "crappy code" at all. Even code that is not as performant as it could be is only "crappy" if it's affecting the bottom line (which it often does). But so-called bad code that is yielding higher profits, hard to call crappy.

                • cjfd 2 days ago

                  It is you who starts to talk about 'art' en 'poetry' but these words do not come from what you are reacting to. One thing you seem to assume is that the 'crappy code' works and therefore the concerns about its crappiness must be about irrelevant things like 'art' or 'poetry'. However, the working of what I would consider crappy code is generally highly tenuous. There has not been found a bug, YET...., but one difference between crappy code and good code is that in crappy code one is quite sure there are lurking many bugs that are just waiting for the right circumstances to occur in practice. Also when bad code is changed, this is a much riskier affair because it is difficult to be sure that no unwanted side-effects were introduced.

                  There is a hypothesis that the crappy code was faster to write. At some point, this becomes false because one also has to spend time fixing the bugs. I would wager that this duration is measured in weeks, rather than months. From which it follows that the picking crappy code for speed is actually foolish and lowers profits for all but the most simple projects.

                  • bschmidt1 2 days ago

                    > must be about irrelevant things like 'art' or 'poetry'

                    If by "bad code" you mean something related to syntax, convention, or code that "might have bugs" (wtf), there is still a case it's actually "good code" if it's more readable, was a quicker solution that yields higher profits, is a less error prone approach to the larger management of the codebase albeit less performant etc.

                    > one difference between crappy code and good code is that in crappy code one is quite sure there are lurking many bugs

                    Sounds too superficial/judgmental and not evidence-based. If there is a bug there is a bug. Even perfectly written code to the best possible standard can still be code that does the wrong thing.

                    • orwin a day ago

                      Poor architecture/design make code unmaintanable, or at least very expensive to maintain.

                      I would rather have my junior spend 3 more days to understand the FSM we use to handle our front before changing anything than him adding 2 random useState an a random useEffect because it just works.

                      How you handle your data is also very telling of the code quality. I'm not against the "write shit fast, fix later", it is in fact how i do my stuff, but once i have a functioning prototype and basic mocks, i then spend a long time in my models.xxx file because modeling data is like 30% of the job.

                      I have an example of bad data modelling: your object (that is a data representation) have fields that in certain case will be empty and you know it. Some people will ignore them. In 90% of the cases, this is a mistake that will lead to mistake down the lane. If you can use discriminated unions and don't because "it's faster" (it takes literally 2 minutes to do), you are probably writing bad code. It's not about idiomatic or not following conventions (those help) or not typing your data, it's about bad modeling choices.

                      • bschmidt1 a day ago

                        > I would rather have my junior spend 3 more days to understand the FSM we use to handle our front before changing anything than him adding 2 random useState an a random useEffect because it just works.

                        React hooks obsoleted most use of state management tools years ago (there is even a native useReducer now so you don't have to install Redux just for that), especially if they're using SSR (Next.js) where state management has been moved to the server. There are still some cases for installing a global state management library in the FE, but usually useState / useEffect and custom hooks is enough for most React projects.

                        The problem is you came up with a heuristic in your mind that "global state management is pro, useState is amateur" but that isn't true.

                        Lets use a real example: If I worked on your team and pushed a <LoginForm /> component that captured email/pass with useState, you would tell me to move the username and password to a global state management library? Why? Dogma? It would be the wrong call.

                        • orwin 21 hours ago

                          We don't use Redux and use useReducer.

                          A Login page is typically a page that if you don't use a FSM, i will make you redo your work. How do you handle MFA? Errors, including network errors since we work with offshore stations that don't have the most stable connexions? I don't see a single way using a handful of states wouldn't result in poor code. What do you do if a new oidc provider will be used? Or if we migrate to AWS and use cognito, what states should you remove, what should you add? How to you order the rendering?

                          Nah, if you don't want to reuse our hooks and functions that's fine, but you need a decent architecture, and using a handful of state is not it, especially not for a login page. As long as you have a process to follow in the component, not using a reducer will hurt you and the maintainability (we avoid putting business logic on the front-end to be fair, but sometimes you have no choice). And simple component that just display shit (thus don't need a reducer) aren't often given to juniors are this part of the job is uninteresting and quick to do for non-juniors. We tend to do a lot more backend and ops than front anyway.

                          • bschmidt1 18 hours ago

                            Didn't say MFA, said state of username / password (useState is fine for that).

                            Also said "use hooks", not "don't use hooks" and never said don't re-use functions.

                            Would hate to be on that team, I bet those PRs are brutal.

                            • orwin 16 hours ago

                              Exactly what I meant to say, as soon as you have to add complexity, just adding useState over and over breaks, and that's what I call bad code.

                              It's fine if it's just a get in a component out of the way, we do not use a reducer to print our 'about' page, but typically the login is where a lot of logic has to happen.

                              I think I misunderstood your comment, you talked about a global manager and I thought you talked about our library.

                              And since we pair/mob program often enough (10 hours a week roughly, per affinity or when someone ask for help), our PR meetings are more a way to show off to the whole team a new idea or present library upgrades, but it's true that we are quite brutal, especially when i compare with my previous job where I worked with Indians and north Americans, I think it is cultural though.

                  • ChrisMarshallNY 2 days ago

                    I have found that "it depends" is an almost universal solvent for all technical quandaries.

                    I have found in my experience (and I have a lot of that), that the search for "One Solution To Rule Them All" is a snipe hunt. You can't get there from here.

                    It always (in my experience) comes down to context[s].

                    That "[s]" is important. There's the current context, and then, there is the future context.

                    You survived your baptism in fire to live to keep delivering software.

                    That's great. It's crap software that got you here.

                    Time to rewrite it, so we now have software with a future

                    Right?

                    OK?

                    That's what we'll do...right?

                    Oh, for Cthulhu's sake, what do you mean we need to keep building on our foundation of sand?

                    Congratulations. You now not only have technical debt; you have technical bankruptcy, coming down the road.

                    Better sell the company fast, before the bomb goes off...

                    • Viliam1234 19 hours ago

                      The mythical "later" never happens. Today we need to get version 1.0 to the market ASAP. Tomorrow we will need to get version 2.0 to the market ASAP. Etc.

                      It's like people who promise that they will stop smoking later. Twenty years later, they usually still smoke. Twenty years later, if the software still exists, all the technical debt tickets will probably still be in the backlog.

                    • OrigamiPastrami 2 days ago

                      > If it's business - we had a solution deployed for the customer in less than an hour.

                      Boeing was good at finding cheaper solutions to business problems as well. In the end it's society that suffers for our tolerance of late stage capitalism.

                      There is no "right" answer to this. But tolerating crappy engineering because it's cost effective seems like an admission of defeat to people that actually want to make things better. It's not so much letting perfect be the enemy of good enough; it's more about the steady decline in quality because that's what we incentivize.

                      • andrepd 2 days ago

                        > so-called bad code that is yielding higher profits, hard to call crappy

                        Missing the point of the person you're replying to entirely... Yes you can get higher profits with shittier code, just as you can by building shittier airplanes, cars, bridges, etc. The consequences being exploits, hacks, 737MAX, Ford Pinto, etc

                        • bschmidt1 2 days ago

                          I think you missed the point that it wouldn't actually be shittier code in that case.

                          Some ugly 4 space indented, wrong kind of loops, old Node version, mongo as the main db, no linter, callback hell SaaS platform in 1 file called "server.js" could still be more reliable and yield higher profits and sooner than your masterpiece in Rust.

                          • andrepd 2 days ago

                            Yes, and then your user's personal details go on a darkweb leak.

                            But who cares! You made bank and no law or liability will actually punish you for it, so what the hell.

                            • bschmidt1 2 days ago

                              No need for a dark web, Twitter and GitHub have both leaked user passwords stored in plain text on their own platforms right here on the corporate web.

                              Twitter who struggled to turn a profit (but not to pay its investors who became wildly rich off it) hired artists who chose technology like Ruby on Rails. They should have hired capitalists who breathed jQuery and ate pieces of sh*t like Active Record for breakfast

                    • fidotron 2 days ago

                      A former colleague of mine had a good way to describe it: technical debt is like financial debt, too much will kill you but if you don’t have any you will be outgunned by those that do.

                      The trick is how to manage tech debt properly, and the widespread scrum fake-agile in use provides no means for ever tackling tech debt once taken on. This is one reason for the explosion in SRE teams.

                      • marginalia_nu 2 days ago

                        > A former colleague of mine had a good way to describe it: technical debt is like financial debt, too much will kill you but if you don’t have any you will be outgunned by those that do.

                        Yeah, this is a very astute observation.

                        It's also worth noting that the cost of technical debt is higher for larger organizations. Refactoring is very cheap when you're just one or a few people, but prohibitively expensive to the point of impossible when working in a much larger organization.

                        I think it's generally a bad idea to write code to large-organization standards when you're working alone. It makes your process much more rigid than it needs to be. The great benefit of flying solo or with a small team is exactly how nimble you can be, the small cost of re-writes and even throwing stuff away.

                        • fsckboy a day ago

                          >Yeah, this is a very astute observation.

                          isn't it just repeating the definition/use of debt which is why "technical debt" was called that in the first place?

                          • marginalia_nu a day ago

                            In many cases, points of view obvious to the point of childlike can be easily overlooked and very helpful.

                      • freefaler 2 days ago

                        Indeed, my own experience in my several companies confirms this.

                        Yes, code quality is important, but we write code to solve a problem for the paying customer. If we can't solve it on time and on budget it doesn't matter how well it has been written.

                        If you survive long enough you'll refactor the parts that are important.

                        Also some parts are more important than other, everything with money calculation and potential data loss should be written more carefully.

                        • f819934580bd48f 2 days ago

                          > potential data loss should be written more carefully.

                          Doesn't this apply to any code that touches data intended to eventually be persisted? If so, IMO this applies to a huge portion of all software, I would guess more than half, because writes tend to be much more complex than reads IME.

                          • freefaler a day ago

                            Data loss usually occurs when you "migrate", "backup/restore", "upgrade" data. A stupid internal tool can wreak havoc because it's something non-customer facing with less stringent testing.

                            The bugs on CRUD operations are usually ironed out early and can be limited to a small subset of data being lost. However a mingled migration script from one table to another is a really dangerous stuff but frequently it's treated as "internal tool".

                            Floating point calculation and storage is also tricky and should be written/tested with greater care.

                          • Spivak 2 days ago

                            I've always called this "good problems to have." If you're at the point where your slapped together solution doesn't cut it anymore then it means you're successful enough to actually need better.

                            Don't use the solutions to hard problems when you don't have hard problems yet. Because they're making trade-offs to meet constraints that you're not under. Ranch dressing at the grocery store has to be shelf stable and they make a bunch of compromises to get it to that point. The ranch dressing you make it home can be better easily by just ignoring those constraints.

                          • bigstrat2003 2 days ago

                            > Author isn’t wrong per se, but code purity isn’t always a worthwhile goal, and needs to be balanced by the needs of the business.

                            I would phrase this slightly differently: code purity is always a worthy goal, but it's not always an attainable goal. As you said, sometimes the needs of the business have to get in the way even though it is a worthy goal.

                            • mewpmewp2 2 days ago

                              It is a potentially misleading to think of it as a goal in terms of raw calculations.

                              If we parallelize it to debt should it be your goal to have 0 debt and why?

                              Shouldn't you first consider what is the interest rate of that debt and what do you gain by having this debt as opposed to not having it?

                              If debt has 0% interest, and you don't have limit on debt, why not just keep taking debt? What if debt has negative interest?

                              The goal should be to determine what is the optimal approach after considering all those factors and then take those approaches.

                              Some people have principles that they don't want to owe anything to anyone, but this will make them take suboptimal decisions. They assign this emotional value to something that is actually an arbitrary concept.

                              • undefined 2 days ago
                                [deleted]
                              • tdeck 2 days ago

                                Another way to put it is that those colleagues are 4 teams away and 2 promos ahead before anyone has worked out exactly what went wrong and whose fault it was.

                              • stouset 2 days ago

                                So much of our “ship fast” culture is based around end-user application development, where it’s a reasonable and defensible approach.

                                But the further away you go from end users toward libraries, then internal services, then even further toward infrastructure, the slower and more thoughtfully you should move. These things often have far less rapidly changing requirements, and getting it right pays dividends. Or more realistically, blasting something half-baked out results in drag on your organization that you end up having to support for forever.

                                On a slightly different axis, APIs should be built with more thought and care than internal implementations. Backward-incompatible API changes are hard. So start out by building an API that expresses the logic your consumers want to implement. README-driven development works great here: literally write the README that showcases how people would use your API to do a variety of tasks. Then you can iterate as many times as necessary on the code, while having to iterate on the exposed surface area far less than if you just exposed today’s internals as the API (which is sadly the norm).

                                • sonofhans 2 days ago

                                  This, exactly. Rapid iteration on user control surfaces is good; rapid iteration on public APIs is bad.

                                  Edit to say — rapid iteration of UX is good as long as it’s goal-aligned and has an endpoint. Set a goal, iterate and measure until you achieve it, then leave it alone.

                                  • rqtwteye 2 days ago

                                    "Rapid iteration on user control surfaces is good; rapid iteration on public APIs is bad."

                                    I think rapid UI iteration is bad once a product has reached a certain maturity. I absolutely hate it when a tool I use often, suddenly changes its interface without any discernible benefit. I am fine with yearly changes but the constant churn is really annoying. MS Teams is a big offender here. They constantly change stuff but nothing gets better, just different. And a lot of UX guys seem to feel it's best to take away features that only a few percent of users are using.

                                    Compared to the progress we made in 1990s and 2000s, it feels like most companies are just moving buttons around and making UI elements more difficult to distinguish but otherwise they are out of ideas for actually useful stuff.

                                    • stackghost 2 days ago

                                      I can't think of a UI/UX iteration in the last 10+ years that felt like an upgrade.

                                      Reddit, Gmail, Twitter, Windows, Android, touch screens replacing actual buttons, etc. they all used to be better but big companies seemingly can't help themselves from making their product worse.

                                      • mitthrowaway2 2 days ago

                                        Yes, please leave it alone. Nothing prompts me to leave a service I've been with for a long time than a UX "refresh" after I had years of experience and setting everything the way I liked it.

                                        • rkuodys 2 days ago

                                          I think this is such an interesting issue. On one hand as a system developer, you want to keep existing customers happy with what they are used to. On the other- you want to grow and acquire new ones which requires upgrades to existing processes till you reach a limit - you need a new ui/ux. And what do you do? Maintain N versions?

                                          • bigstrat2003 2 days ago

                                            The problem, as usual, stems from businesses prioritizing growth above all things (including the existing customers). There's absolutely nothing wrong with having a stable business that turns a respectable profit, but modern day American business culture is allergic to the idea.

                                      • angarg12 2 days ago

                                        > even further toward infrastructure, the slower and more thoughtfully you should move. These things often have far less rapidly changing requirements

                                        I used to think that, until I worked on my first large scale system, infra heavy. It turns out it works both ways.

                                        If changing infra is hard, slow, painful and risky, people will be less inclined to do so. If changing infra is fast, easy, and with low risk, people will be much more inclined to change things.

                                        Even if you had very stable requirements (doubtful in this day and age), I see no reason why you wouldn't build your system in a way that is easy and safe to change, for the day when it's needed.

                                        • stouset 2 days ago

                                          I don’t disagree at all, but I want to be clear that my point is more about upfront thoughtfulness and less about continual ability to iterate.

                                          Being careful upfront often increases your ability to iterate rapidly because you aren’t constantly dealing with the consequences of poor early decisionmaking that causes calcification.

                                          • auggierose 2 days ago

                                            Because you cannot build a substantial system such that it is easy and safe to change. Especially for changes you didn't foresee.

                                            • angarg12 2 days ago

                                              Hard disagree. The system I'm talking about is the largest scale system I've worked with (millions of QPS, thousands of servers). We built it in such a way that we were able to rewrite entire parts of our stack easily and relatively safely. The techniques and tools to do it are widely available today.

                                              • auggierose a day ago

                                                Good for you. Modular programming goes a long way, of course, but I'd say that your changes were then those that could be foreseen, for example by drawing the right modular boundaries from the start.

                                            • GauntletWizard 2 days ago

                                              You should still ship early and ship off in with infrastructure projects, but the changes you're going to make are going to be a lot smaller, and the big ones are going to be planned far in advance. You will still need big changes, and even your small changes require subjectively "more" thought.

                                              Both things are true: you should move slower and more thoughtfully on infrastructure projects, and "ship often" is still valuable advice and a worthwhile goal

                                            • tetha 2 days ago

                                              Mjeah. It is our goal at work to enable our teams to deploy changes to their systems in production within minutes. And this works and the teams utilizing it get commended for it.

                                              But I also need to plan and execute a major database upgrade with ~250 applications depending on it. I will be very happy if I can have a solid, generally accepted plan in a month or two. It will just take 1-2 person-days to eventually execute the updates, but it will take 6 - 12 months to get there. And from what I hear from colleagues and customers, that's fast.

                                              • bluGill 2 days ago

                                                Great, butmy end users don't live in fast internet range. every few months they spend some time in 2g cell range. upgrades mean mailing a usb drive. we have to get quality right as fixes cannot be rolled out fast.

                                              • hinkley 2 days ago

                                                TDD is trying to accomplish the same thing. Here’s the shape of the thing, now make it work. But maybe we should just be writing the manual first. Though I would say we need something akin to “code coverage” in that doc, even if it’s just QA changing the font color of every line that is now true from red to black, so you know where the gaps still are.

                                                • stouset 2 days ago

                                                  Sort of, but sometimes I feel like TDD approaches the forest by making each tree first one by one.

                                                  I really like writing a usage README first, since I don’t have to make anything work along any axis yet but I can play freely with the shape of things, figure out how to make the whole thing consistent, and experiment on what boundaries it makes sense to break components apart so they can be mixed and matched.

                                                  This does require a decent amount of engineering experience to both figure out what your consumers really need and also to design something that is actually implementable.

                                                  • hinkley 2 days ago

                                                    We are doing this weird zigzag of a gradient descent because we know that things are bad, but we don’t know exactly how they are bad. We don’t know exactly which direction is “downhill” and which is “uphill”, so we turn around and head somewhere in a 120° code of where we think is the opposite direction. But it’s not the right thing, it just has some of the opposite qualities of the wrong thing.

                                                    It’s better than post-disaster politics, where “something must be done, this is something, so we shall do it” but it has an aftertaste of that same sentiment, if that makes sense.

                                              • lordnacho 2 days ago

                                                One of the great things about working from home is that I often don't do anything. As in, I'm not even by my computer.

                                                I'm still thinking about what to do, but I'm not implementing anything. I'm not typing stuff, I'm not waiting for a compile, I'm not outwardly moving the project forward.

                                                But the project is moving forward.

                                                Inside, I am considering the tradeoffs. I'm thinking about what the business needs, and what things will look like when I'm done.

                                                Now and again, things come together and I write the code. It's a lot less frantic than 20 years ago when I started. I throw away fewer things, and there is less time wasted. Any bugs that I write tend to be superficial, easy cleared up. Back when I was younger, "bugs" would be architectural decisions that were made in the frenzy of an office, and would require a lot of work to fix.

                                                • greenbit 2 days ago

                                                  It's kind of maddening, after having the space to Just Think during the WFH days, to be back in the office and any time you stop typing for more than 30 seconds risk being interrupted by co-workers who think you're Not Busy.

                                                  • jauntywundrkind 2 days ago

                                                    I admire the heck out of the two coworkers I've had who were smart enough to stand up & go for a walk to think. Or to have a 1:1.

                                                    I didn't face a ton of unscheduled conflict for my time, and there were many rooms available at that job. But the change in perspective was amazing, just so much power to help me really consider things in new light.

                                                    It's funny because I grew up with Steve Roberts as my role model of role models, as the guy who showed me that being an adult could be fun & interesting, with his work-from-bike Winnebiko. And I was a seasoned coffee shop coder, which I found amazing with its change of scene & deliberateness. But seeing Adam have such a practice of getting up, grabbing a notebook (also a seasoned writing-things-down person; another key element of Hammock Driven Design), and going for a stroll (DC's Rock Creek Park was a bit over half a mile away) was amazing, really opened me up.

                                                    As other comments mention, Rich Hickey's Hammock Driven Design is excellent, amazing. Some deliberateness about figuring out what we are doing, letting the waking mind come up with problems and possibilities, and giving time and written down ideas for the passive/sleeping mind to cycle through options & combine them... Kind of like protein synthesis, a soup of amino acids/ideas and your mind as rna, blindly bumping elements together to see if they bond. https://youtu.be/f84n5oFoZBc

                                                  • mhuffman 2 days ago

                                                    >One of the great things about working from home is that I often don't do anything. As in, I'm not even by my computer.

                                                    >I'm still thinking about what to do, but I'm not implementing anything. I'm not typing stuff, I'm not waiting for a compile, I'm not outwardly moving the project forward.

                                                    This is literally the nightmare scenario of middle managers and c-suite managers about wfh employees. You walking around visibly doing nothing and them paying you to do it! Somehow when you do the same thing near your cubicle or in your office you "look like" you're working so that is much better!

                                                    • mewpmewp2 2 days ago

                                                      > One of the great things about working from home is that I often don't do anything. As in, I'm not even by my computer.

                                                      Couldn't agree more. I think one major advantage of working from home is that you can go for a walk whenever you feel like it without having to feel guilt or feel like you have to justify it to anyone. Not only is it amazing against stress and for health reasons, but it's also amazing to get another perspective with your thoughts left free to run.

                                                      Not to mention all the other productivity and efficiency ruining obligations in the office like having to feel you have to stay until certain time even though at that point it would be more efficient to do something else etc.

                                                      • emidln 2 days ago

                                                        Rich Hickey calls this "hammock time".

                                                        • mihaaly 2 days ago

                                                          This way, I like to work in the shower or during commute of a crowded bus staring outside. But the best ideas come in the can, office or home bathroom, does not matter. : )

                                                        • klodolph 2 days ago

                                                          I don’t know how many k hours of coding I have. 10k is long in the rear-view mirror.

                                                          My advice? Ship fast. The way you get good is by being fast.

                                                          Think of two junior engineers, we’ll call them Uno and Dos. Uno is working hard on a feature and wants to get it working, and working right. Uno spends two full weeks working on it and then sends out a PR. Dos starts by thinking “fast”, and figures out how to send a PR within only two days. This PR is, of course, horribly incomplete. Uno’s PR is bogged down in review because there are major problems. Dos, on the other hand, gets some really quick feedback from the team lead saying “you can extract this function and write a test for it, please do that.”

                                                          The same applies not only to junior engineers working on a small scale within a team, but to large scale projects being shipped by the whole team. Ship it fast, get feedback fast, and let it blow up in your face if you think you can survive the consequences.

                                                          The same applies to me. The best stuff I have ever shipped has been shipped fast and fixed afterwards.

                                                          If you want to raise the quality of your code, the way you do it is by meeting the requirements fast. If you beat the clock when it comes to baseline requirements, you get extra time to refactor and redesign components.

                                                          There are also a million things you can only learn by shipping code. Learn those things sooner; ship fast.

                                                          • npalli 2 days ago

                                                            This whole thesis rests on the team not knowing what to build and shipping fast to get more learning cycles. Works if you don't know anything (said juniors) or new fields (like internet or social or mobile etc.). Lot of places (including formerly new fields) that is not true anymore. Not everything is move fast and break things - which was Facebook's motto until 2014.

                                                            • klodolph 2 days ago

                                                              I say this is wrong, and the true reason to ship slower is when shipping something wrong is catastrophic.

                                                              Let’s say you are making something well-understood like a PCB. To me, the “ship fast” option is to make a prototype PCB fast, even if it doesn’t meet the design constraints (say, size, power consumption, cost),

                                                              That’s because very few things we build are so well-understood that you can design and then ship. Development is, in its most ideal form, highly iterative and incorporates data from the field as soon as feasible. In the PCB design scenario, we want the prototype sooner because we can learn things like “this design is too sensitive to EMI”, which may necessitate a redesign or at the very minimum re-spinning the PCBs.

                                                              PCBs are very similar to ICs. ICs get fewer prototypes and a more careful shipping process because it can cost millions to do a new stepping. Not because IC design is poorly understood or mysterious, but because mistakes are costly. That is the real reason you would slow down. Maybe you spend more time and money doing simulations for your ICs, maybe you have them go through more design reviews.

                                                              Likewise, shipping a bad medical device or bad space probe is usually catastrophic.

                                                          • jakelazaroff 2 days ago

                                                            Strongly disagree with “Do the Refactoring First”. It is inevitable that your project will grow in ways you can’t anticipate. If you spend too much time up front on architecture, one of two things will happen:

                                                            1. You build abstractions that are not useful in the future, or

                                                            2. Worse, you build abstractions that constrain you from making future changes.

                                                            Of course, either of these can happen anyway, but at least then you haven’t wasted a bunch of time refactoring before you know how your code base will grow.

                                                            I prefer this approach from The Grug Brained Developer:[1]

                                                            > next strategy very harder: break code base up properly (fancy word: "factor your code properly") here is hard give general advice because each system so different. however, one thing grug come to believe: not factor your application too early!

                                                            > early on in project everything very abstract and like water: very little solid holds for grug's struggling brain to hang on to. take time to develop "shape" of system and learn what even doing. grug try not to factor in early part of project and then, at some point, good cut-points emerge from code base

                                                            > …

                                                            > grug try watch patiently as cut points emerge from code and slowly refactor, with code base taking shape over time along with experience. no hard/ fast rule for this: grug know cut point when grug see cut point, just take time to build skill in seeing, patience

                                                            > sometimes grug go too early and get abstractions wrong, so grug bias towards waiting

                                                            [1] https://grugbrain.dev/

                                                            • cholantesh a day ago

                                                              > sometimes grug go too early and get abstractions wrong, so grug bias towards waiting

                                                              Tried to hammer this into an intermediate level colleague recently while pairing and they just wouldn't accept it; eventually I said, ok let's do it, and as expected it ended up just creating a couple more days of toil for us. Hoping this turned out to be a learning experience for them.

                                                              • pphysch 2 days ago

                                                                Yes the author strikes me as a early/mid career SWE rather than a seasoned professional (10K hours is often used as an allusion to "mastery").

                                                                1. Junior: hack a solution from A to B by any means necessary

                                                                2. Mid-level: wait, design matters. Abstract everything up front!

                                                                3. Expert/mastery: wait, complexity also matters. Consider many paths and finds sweet spot that is simple, robust, extensible, maintainable.

                                                                • ilrwbwrkhv 2 days ago

                                                                  I think the intermediate level, do the refactoring first, clean code mentality is a big one to grow out of.

                                                                  The ultimate mastery is to think about "what does the computer need to do?" If there is a button click and some data has to be aggregated, those are two operations that should result in two blocks of code changing, the event handler and the db select group by (or other data source).

                                                                  Everything else beyond it is extraneous code and you should think very carefully if you are adding any line beyond that.

                                                                  The worst in the typescript world is elaborate types which do not work all of the time. Better to have implicit types doing most of the heavy work and remember you are building software, not doing type system research.

                                                                  • jakelazaroff 2 days ago

                                                                    For me, the most important thing in this situation is coupling. The code implementing a feature may be an ungodly mess, but by minimizing its coupling to the rest of the system I make it easy to improve (or remove) later. I would much rather have messy and confusing code that is self-contained than an elegant abstraction with a large blast radius.

                                                                    • hinkley 2 days ago

                                                                      And you do that decoupling by…

                                                                      Refactoring.

                                                                      So I’m a little confused about why it sounds in this whole thread like we are vilifying refactoring without actually saying we are doing so. It’s weird.

                                                                      • jakelazaroff 2 days ago

                                                                        No, I’m talking about the first time I write something. At that point in the game, my highest priority is to minimize the coupling between that code and the rest of the system (rather than, say, performance).

                                                                        • pphysch 2 days ago

                                                                          Refactoring "up front" is what people are taking issue with. It's extremely rare to have a project where you know every requirement and they never change "up front" before writing any code.

                                                                          • hinkley a day ago

                                                                            Either Fowler’s 2nd edition made some pretty big changes I’m unaware of, or we are all using very different definitions of Refactor. Do you guys mean “redesign”? Because that’s a very different word from “refactor”.

                                                                    • valval a day ago

                                                                      The article reads a bit like those blog posts from junior developers in third world countries who are trying their hardest to prove that they’re capable developers who know what they’re doing, in order to make it out of their current situation.

                                                                    • Degorath a day ago

                                                                      Refactor first and overarchitecting up front are completely different things, though.

                                                                      • jakelazaroff 11 hours ago

                                                                        From the article:

                                                                        > What I propose is to spend your first 40-50 hours planning and refactoring. Just create a few controllers, brainstorm how that would scale in the future, refactor, and then continue.

                                                                        That is overarchitecting up front. What I would propose is to follow those steps but stop after “create a few controllers”.

                                                                    • leksak 2 days ago

                                                                      Do ship fast until it is known what the application will even be and what the feature-set is and what needs the user actually has and not just what it is believed they need.

                                                                      Don't sink a bunch of time into "cleanly" exploring the fog-of-war. Gather as much insight as possible as soon as possible. Only then will you be equipped to actually architect for the domain as it actually is rather than what you the developer think it might actually be.

                                                                      • iveqy 2 days ago

                                                                        I strongly disagree. You should always keep the code as simple as possible and only add abstractions once you really need them.

                                                                        Too many times I've found huge applications that it turns out be most scaffolding and fancy abstractions without any business logic.

                                                                        My biggest achievement is to delete code.

                                                                        1. I've successfully removed 97% of all code while adding new features. 2. I replaced 500 lines with 17 lines (suddently you could fit it on a screen and understand what it did)

                                                                        Also: https://www.youtube.com/watch?v=o9pEzgHorH0

                                                                        • halfcat 2 days ago

                                                                          Yes. Battle future unknowns by remaining simple and flexible, not by trying to predict the future.

                                                                        • l5870uoo9y 2 days ago

                                                                          When I program something new and challenging, whether I want to or not, I follow Kent Beck's pattern[0]: “Make it work, make it right, make it fast.”. It seems unavoidable.

                                                                          [0]: https://en.wikipedia.org/wiki/Kent_Beck

                                                                          • bluGill 2 days ago

                                                                            If edison had spent some more time thinking he would have perspired a lot less. Too often there is no path from one to the next other than starting over.

                                                                            If you have the wrong algorithm your existing tests won't help much as the likely have wrong edge cases.

                                                                            • IshKebab 2 days ago

                                                                              I dunno if you can always do them in order. I've seen so many projects fail because they left "make it fast" until the very end ("but premature optimisation!") and then found they'd written tens of thousands of lines of code using a language or architecture that was fundamentally slow, and making it fast would require a full rewrite.

                                                                              I think it's fine advice in some circumstances but like so much coding advice the real skill is not knowing the advice, it's knowing when to apply it.

                                                                              • mewpmewp2 2 days ago

                                                                                Out of curiosity which projects were those?

                                                                                It must be a very specific use-case, because usually I would see languages usually considered worst for performance being able to scale really, really far.

                                                                                In 95% cases it's usually database being the bottleneck rather than whichever coding language you chose.

                                                                                • IshKebab a day ago

                                                                                  The main one I'm thinking of was a silicon verification system written in Python. Not the only reason the project failed but the fact that it was so janky and slow definitely helped slow progress to a crawl. It didn't have a database.

                                                                                  Speaking of Python, I also recently wrote a tool in Python that was getting a little slow and bloated - I rewrote it in Rust and managed to reduce the runtime by 40x and memory use by 3x. This one wasn't mission critical but you can see the scale of the issue. And no there wasn't any realistic way I could have found a hot spot and just written that part in another language. That rarely helps in my experience.

                                                                            • neeleshs 2 days ago

                                                                              In my 25+ years of experience, any code you write today, however beautiful you think you wrote it, will get stale in a few years and has to be changed/enhanced to adapt to the new reality.

                                                                              With experience, you learn to find balance between pragmatism and purity more often than not. You will still not always be right.

                                                                              It is all still a mix of skill, experience, team and external factors.

                                                                              • hinkley 2 days ago

                                                                                When I’m working in lower-case c clean code, the amount of friction due to regrettable decisions made before everything became clear is unfortunate but manageable. When we have decisions that aren’t just regrettable but daunting (how on earth am I going to unravel this warren of pain and stupidity enough to get this thing to do what it’s supposed to do and only what it’s supposed to do??) then the full weight of the sins of the past hits, and we start making proclamations and resolutions about Never Again.

                                                                                You don’t have to run away from the falling axe or ban axes. You need to not be there when it falls. And in the context of software what that looks like is very difficult to explain without ascribing unnecessary or even misguided qualities to the differences. We keep describing analogs, symptoms or harbingers of the real problem, and those fall down or distract.

                                                                                • undefined 2 days ago
                                                                                  [deleted]
                                                                                • diffxx 2 days ago

                                                                                  I agree with the author that slow can be good and that taste and diligence can trump raw smarts.

                                                                                  I think what is often missed though is the opportunity cost of shipping bad products. Our industry lionizes fast delivery to juice short term earnings but this is very often at tremendous long term cost. When your revenue depends on shoddy products, you must devote an excess of resources to patching the holes that are slowly sinking your ship. The best people will tire of this and jump aboard the next vessel that offers better working conditions and/or higher compensation. But of course one never escapes the fundamental problems by job hopping.

                                                                                  To build something great, reliable and high value takes time. If it were easy, the market would be awash with cheap high quality products. It clearly isn't.

                                                                                  For things to improve, I believe that a small group of workers will likely need to join together and sacrifice short term earnings to build viable long term companies on a different set of ethics and values. I have personally made this sacrifice and am working on something I think is great and valuable that I could not possibly do within a typical company.

                                                                                  I have optimism that soon alternative approaches to building companies will emerge outside of the current VC funding model, which I believe has run its course. There are many, many software developers who are wealthy enough to sacrifice short term compensation to build more equitable companies with longer term vision and with a much higher ownership percentage that will pay off in the long run.

                                                                                  • firefoxd 2 days ago

                                                                                    What 2 decades of coding taught me is, it all depends on the company. We all aspire to write clean code that scale. But most often then not, you inherit the code.

                                                                                    If you work for a company that is built to sell, you will code fast and break things. Each feature is a show case to future buyers.

                                                                                    If you work with "experts", you will write clean, scalable code that no one will buy. The priority is the code, not the product.

                                                                                    If you are lucky, you'll work in a company that is profitable without a hyped up product. Here you have the bandwidth to refactor.

                                                                                    I've worked in several companies that are built to sell. Tech debt is ignored unless there is a major breach.

                                                                                    • undefined 2 days ago
                                                                                      [deleted]
                                                                                    • sobellian 2 days ago

                                                                                      You should usually wait to refactor until after you write the code and preferably ship it to someone.

                                                                                      You may not understand what makes a correct implementation. Don't waste time refactoring incorrect code.

                                                                                      You may not understand what makes a performant implementation. Don't waste time refactoring code that's too slow.

                                                                                      You may not understand what the user wants. Don't waste time making something no one wants.

                                                                                      You may not understand how the software needs to evolve. Don't waste time making something extensible in a way that will never happen.

                                                                                      • muspimerol 2 days ago

                                                                                        It's important to note that this is only really relevant advice for a specific type of startup that is still trying to rapidly iterate to find product market fit.

                                                                                        Personally I find it incredibly annoying to work on and with with products that were developed like this. There are so many half baked features that technically "work" but are slow, buggy or difficult to integrate with.

                                                                                        • sobellian 2 days ago

                                                                                          It's relevant if you need to rapidly iterate, period. The test is not whether you work at a start-up, but how well you understand your problem. I am currently doing a lot of automated design work with optimization over highly non-convex constraints. Good luck writing that without rapid iteration.

                                                                                          • muspimerol a day ago

                                                                                            Fair point, but I have seen a lot of shitty software developed with this mantra. Usually because the "iterate" part is forgotten in favor of the next "rapid" development. I agree that the quickest way to learn whether your solution is valid is to ship & experiment. But once you know the solution (which is sometimes not even that complicated) then you should really take the time to produce a solid piece of software before moving on.

                                                                                            But I agree, my original comment is probably a little too critical. There are valid times to rapidly iterate and ship. When it turns into the _only_ way you ship software, I think it becomes a problem.

                                                                                        • hinkley 2 days ago

                                                                                          One of the very frequent challenges I have with optimizing code, is that unless the problem is very highly contained, first I have to look at this code that’s all over the place, both physically and emotionally, and just try to figure out wtf it’s actually trying to do. I can’t replace it unless I know the requirements. The intent.

                                                                                          Give me a piece of code that’s wrong but clear about it, and we’re good. I can get in and out and move on to the next most tricky:value ratio’s problem.

                                                                                          Refactoring it to that point will always pay dividends. Even if it’s just for the next person trying to add more functionality in this area.

                                                                                          • sobellian 2 days ago

                                                                                            I don't think you necessarily need to optimize before you make the code "clean" but you should at least understand what it will take to make it performant. This is a stronger requirement than it might sound like since most programmers are quite bad at predicting what will perform well without profiling first.

                                                                                            So knock together a prototype and profile that to understand what the bottlenecks are in your program, then you have an informed baseline of how the program needs to fit together to function well.

                                                                                        • renlo 2 days ago

                                                                                          Agree that the repository/service pattern is a good way to adhere to separation of concerns and make refactoring and readability easier.

                                                                                          That said, I really disagree with any precommit checks. Committing code should be thought of as just saving the code, checks should be run before merging code not saving code. It'd be like Clippy preventing you from saving a Word document because you have a spelling error. It's a frustrating experience.

                                                                                          I can make sure my code is good before I submit it for review, not when I'm just trying to make sure my work has been saved so I can continue working on it later (commit).

                                                                                          • Foreignborn 2 days ago

                                                                                            Most pre-commits I’ve seen are usually formatting/prettier.

                                                                                            But if need be, I will spam my commits locally with `—no-verify`. Once the code is ready, I reset to head and remake them as nice, conventional commits.

                                                                                            • Degorath a day ago

                                                                                              While I like abstracting storage into a repository class of sorts, this crap of "userService" needs to die already. I've seen too many bad codebases that stick everything user related into that one service that ends up having 8+ completely noncohesive functions.

                                                                                              • BeetleB 2 days ago

                                                                                                Usually you have those checks when pushing, not committing.

                                                                                              • DangitBobby 2 days ago

                                                                                                Commit hooks are not the place for test checks. You want developers to commit and push work so they don't lose it to catastrophic disk failure, theft, etc. Instead, test on push, or before merging. If you like to enforce "atomic commits", well, there's always interactive rebase.

                                                                                                • ashu1461 2 days ago

                                                                                                  The refactoring piece is a great advice. That is the only way to keep the codebase sane and relatively free from tech debt. And if it is not the part of the process, it would never get prioritised.

                                                                                                  • bckr 2 days ago

                                                                                                    Tidy first!

                                                                                                    Make the necessary change easy to make

                                                                                                    Then make the necessary change

                                                                                                    I’m paraphrasing Kent Beck

                                                                                                    • IshKebab 2 days ago

                                                                                                      Yeah I definitely agree. Any time spent prototyping is easily worth it (and I mean real prototyping, not "prototype that you add features too until it's the product").

                                                                                                      I once spent a few weeks protecting a project with different GUI toolkits. I think I spent a week each on Qt, AngularDart and Vue. I wanted to spend one more week trying React but my boss was just itching to "start" and couldn't wait one more week.

                                                                                                      We went with Vue, which turned out to be a terrible decision (I'm not sure about Vue 3, but Vue 2 at least is shit compared to React). Guess what we spent 6 months doing later... all to save one week.

                                                                                                    • jilles 2 days ago

                                                                                                      Lost me at 99% is developer experience. There is so much more philosophy involved in what makes good software.

                                                                                                      • kopirgan 2 days ago

                                                                                                        Think instead of abstract arguments it's better to think about concrete examples. I can think of lots of software that's survived, prospered with a "get it out of the door, fix it later" approach. Lol at risk of being attacked, Microsoft is classic case.

                                                                                                        Love to hear of specific (not company secret of course) cases where projects, products or even companies died doing such shortcuts.

                                                                                                        • jjallen a day ago

                                                                                                          Aren’t we usually coding for another goal though?

                                                                                                          Does shipping slow help us achieve those other goals?

                                                                                                          If we look at coding purely for the goal of coding and having maintainable code, then of course we should ship slowly. But that’s not the only goal of most coding projects.

                                                                                                          • redbell 2 days ago

                                                                                                            > Most people think that great engineers are magicians who build applications in a unique way that no one can understand.

                                                                                                            This reminds me of Ninja Code: https://javascript.info/ninja-code

                                                                                                            • fsndz 2 days ago

                                                                                                              on the contrary, ship fast, survive, then refactor later. there is no need for premature optimisation.

                                                                                                              • henning 2 days ago

                                                                                                                > I’ve been an engineer for over 7 years now. I have worked on countless projects

                                                                                                                If you've worked on countless projects in 7 years, that means no single project was that big or long.

                                                                                                                > Refactoring a relatively big software, for example, with over 70,000 lines of code, can take 30-40 hours

                                                                                                                I admire the author's ability to casually introduce completely arbitrary definitions of "relatively big" and that "refactoring" 70,000 SLOC only takes "30-40 hours" without giving any information about what the nature of the refactoring is.

                                                                                                                > Now imagine if we didn’t implement a good architecture from the beginning

                                                                                                                This post does nothing to define what "good architecture is" or prove that adding additional indirection helps anything. Code re-use is about more than just not putting query and service call logic in a controller method. The contrived examples about adding logging to a codebase that has no logging (why does the app have no logging? why does it need to be added now when it didn't before?) only makes sense if every part of the application conforms to the same interface you've introduced. Considering that a large application may have many different features and do lots of different tasks, this may not happen in which case you need one interface for each situation or create some stupid abstract thing that can handle everything.

                                                                                                                The stupid pre-commit setup makes it impossible to share a branch you're working on if you can't figure out why a test won't pass and want to get help from someone on your team. Or you have a WIP codebase where tests are broken and want to pass it off or show it to someone else.

                                                                                                                • jondwillis 2 days ago

                                                                                                                  From the looks of the “good” code referenced in this article, maybe the author needs another 10k hours. `data: T | any` lmao, just WHY? why try to use generics if you’re going to allow any..

                                                                                                                  • j45 2 days ago

                                                                                                                    Shipping fast might be confused for shipping smaller complete updates.

                                                                                                                    The more flexibility that's maintained in the start, the more things the code can try to solve.

                                                                                                                    This is also easier with less code written in general.

                                                                                                                    • makach 2 days ago

                                                                                                                      Of course we need viewpoints from that perspective as well. It’s a balancing act- I’ve met too many proud developers who never shipped because the idea of perfection. If in doubt, do a risk assessment. Take time to review and evaluate what to do.

                                                                                                                      • hackbot216 2 days ago

                                                                                                                        [dead]

                                                                                                                        • pictur 2 days ago

                                                                                                                          [dead]

                                                                                                                          • bookofbiden 2 days ago

                                                                                                                            [flagged]

                                                                                                                            • wslh 2 days ago

                                                                                                                              As someone who frequently follows HN and Reddit threads, I’ve noticed that while many interventions are discussed (like supplements or diets), nothing truly beats physical activity for improving well-being—unless you have a legitimate medical condition preventing it. Of course, sample size = 1, and everyone’s different, but this has been my experience.