What 10k Hours of Coding Taught Me: Don't Ship Fast

91 pointsposted 5 hours ago
by thunderbong

74 Comments

dahdum

4 hours 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

3 hours 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 hours 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.

mihaaly

2 hours 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 hours 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 hours 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 hours 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

an hour 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.

ChrisMarshallNY

2 hours 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...

OrigamiPastrami

2 hours 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 hours 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

37 minutes 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.

fidotron

3 hours 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 hours 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.

freefaler

3 hours 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 hours 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.

Spivak

2 hours 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

an hour 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

an hour 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.

stouset

5 hours 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).

hinkley

13 minutes 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.

sonofhans

4 hours 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 hours 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

3 hours 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

3 hours 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

3 hours 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

an hour 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

3 hours 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 hours 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

3 hours 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

an hour 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.

GauntletWizard

3 hours 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

4 hours 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

4 hours 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.

klodolph

2 hours 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 hours 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

an hour 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.

lordnacho

4 hours 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

4 hours 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

4 hours 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

mewpmewp2

an hour 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.

mhuffman

3 hours 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!

mihaaly

2 hours 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. : )

emidln

4 hours ago

Rich Hickey calls this "hammock time".

jakelazaroff

4 hours 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/

pphysch

3 hours 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 hours 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

an hour 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.

iveqy

2 hours 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 hours ago

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

leksak

5 hours 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.

diffxx

2 hours 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.

neeleshs

3 hours 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.

l5870uoo9y

4 hours 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

4 hours 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

4 hours 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

an hour 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.

DangitBobby

3 hours 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.

sobellian

3 hours 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 hours 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

an hour 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.

firefoxd

4 hours 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.

renlo

4 hours 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

3 hours 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.

BeetleB

4 hours ago

Usually you have those checks when pushing, not committing.

jilles

2 hours ago

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

ashu1461

5 hours 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

5 hours ago

Tidy first!

Make the necessary change easy to make

Then make the necessary change

I’m paraphrasing Kent Beck

IshKebab

4 hours 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.

fsndz

an hour ago

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

henning

2 hours 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.

makach

2 hours 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.

wslh

3 hours 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.