Ask HN: In your company, how important is code quality vs. getting things done

94 points by maephisto ↗ HN
How much value does your employer put on code quality, design patterns, tested code, test coverage vs. shipping features fast and fixing/refactor it "later"?

92 comments

[ 3.4 ms ] story [ 115 ms ] thread
As a contractor I can see different approaches across companies. Some go for quality over delivery, some for delivery over quality. What I rarely see is balance. There should be a sweet spot somewhere there. Great developers though will produce quality code right off the bat but these developers are costly and you'd need most of your team to consist of those. Its possible to get things done and deliver quality code at the same time. You just need to know which corners can be rounded and when.

Edit: Just to be clear, nobody sets out intentionally and says "lets favour delivery over quality" or vice versa. Its an approach manoeuvred by the personalities in charge and the team as a whole.

Non-tech company in Seattle: Code quality be damned, we need new features made quickly by outsourced teams with no code-review. Then hide them with a feature flag for three months.
Whole range of attitudes actually. Worked in places where all stakeholders were interested exclusively in a working deployed feature and where architecture refactoring "featureless" periods were considered as bumming around. Worked in places where the test setup was choking down development to the extend that it was difficult to complete a feature, and in such cases person was disciplined by overzealous Scrum Master/QA and snitched to the manager.
Perhaps I work for too huge a company, but I'd say it varies greatly from team to team.
I'm a freelancer. Customers usually want to meet deadlines no matter what. Even the ones that agree to delay deliveries usually do it only when they understand that something new happened. A recent example: an integration with a banking API which is still under development is delaying a project. Force majeure.

Almost nobody understands or cares about good engineering, tests and the like. That's not where they are making money from, at least in the near future. However I did have some pleasant experiences.

(comment deleted)
Postdoc in HPC/numerical physics here. Somewhat rarely for my field, my supervisor gave me a lot of freedom during my PhD to `do things properly’ (instead of pushing me to get things done yesterday). While I don’t have 100% test coverage in my (by now) 40k lines of C++, the overall design is sound, documentation exists and covers everything necessary, some tests exists and it is clear that the entire thing is very flexible and new things can quickly be implemented in it.

So far, this approach has paid of tremendously both for me as well as my supervisor, as the reuse value is quite high and performance very competitive, resulting in many projects both within the former chair and also with external collaborations.

40k lines sounds huge... what does your baby do?
Tensor networks, as in the condensed matter theory sense - i.e. matrix product states, DMRG, time evolution, many different physical systems, some different tensor network topologies etc.

Unfortunately closed-source (though open for collaborations), otherwise there’d be a link here.

As I understand, code quality is not a goal in itself, it matters so far as it affects getting things done. So if you compare the two, of course getting things done is more important.
There is often a trade-off between gettings things done in the short term and gettings things done in the long term. All other things being equal (of course they never are...) you'll likely have a much harder time getting things done in the longer term if you pay less attention to code quality.

This is of course exactly the notion of technical debt, and how the debt can compound (that is, you will struggle to get things done more and more the longer you leave your debt unpaid).

Anything which handles business or personal data (so virtually everything making money) has security concerns, and IMHO the first step to good security is a well structured and clean codebase (Note: I'm a dev but not a security specialist)
Quality and testing is less important for us before we have customers. Ocasionally we will rewrite a whole application if people actually use it.
Games Industry perspective: Usually getting things done is more important. Code gets rewritten many times and features change very fast, so not much use or time to try to come up with a solution that lasts that long. Also, once a game is out a lot of the code is thrown away. Engine code usually more durable and stable but also pushed to get it out of the door as fast as possible.
> Also, once a game is out

Curious, what kind of games you work on that still "get out"? I used to work on mobile, now switched to Steam "indie", and in both cases the public release is only the beginning of ongoing tweaking and support.

You're right, my work has been mostly standard (old-school?) AAA games but lately with games being developed more as a service things have changed. Nonetheless, what I meant was there's is a lot of ad-hoc code, specially in gameplay, that only really fits that particular game, so its life is fairly limited. In my experience, that code tends to just get the work done, which is good in my opinion.
> In my experience, that code tends to just get the work done, which is good in my opinion.

Not if you have to support it and build on top of the features implemented with such an ad-hoc approach.

Not the OP or in the games industry, but when Blizzard rereleased StarCraft 1, they made it a point to reproduce all the known "bugs" of the original. By this time, those are treated as part of the game.

I've heard this is true of other games as well: Street fighter (cancels I believe?) and smash (Wave dashing). Sequels reproduced bugs from earlier versions as they came to be seen as features of the gameplay.

In the better places I've worked "getting things done" was the priority. The places that valued code quality always overshot deadlines by enormous degrees (over a year late on an 8 month project, for instance).

Typically I find that code quality isn't too vital, as the majority of big-co systems tend to get re-written from the ground up every few years, rather than modifying and evolving the existing system.

Seems that way at most large orgs. A friend of mine was talking about how some random support desk person will just log in, kill a specific logging process and manually type the path to run it in at a root shell, which inevitably borks things, and due to it happening multiple times a day he has written a unit file so systemd will actually kill the process, fix the now wrecked permissions, and start the logging daemon's unit file properly.

But, the real question is why does a support person have global root access to every server in a large enterprise?

Well, because it "used to be like that" and nothing is as persistent as a stopgap solution. Fun story: Used to work at a 8 year old, heavily growing ad network in customer support and hadn't even officially progressed to engineering yet, but people heard stories about my PHP hacking skills.

So one of the old-timers came by (really fun and totally random guy) and was like... "ah, there's this one thing I thing you could help me, I'm trying to find a solution for these tracking error reports. wait, I'm giving you access"

A few minutes later came my email together with password over MS Lync, and nothing else. And I waited for him to come by with some requirements.

Which of course didn't happen. But what happened instead was that the newly minted Head of IT came by who was tasked of cleaning up the mess after the acquisition and introduce a proper process.

He looked at me very earnestly and just when I tried to think hard what I did wrong he blurted out "WTF ARE YOU DOING WITH YOUR LIVE DB PRODUCTION CREDENTIALS!?"

In the moment I realized what that guy gave me, it was gone already unfortunately.

So long story short, as time goes by and companies grow, there are very different approaches at "getting things done" ;-)

What one person may think is fine might look crazy to someone else. Getting things done seems to be the MO of most orgs though.
Equally important. In my opinion we ship fast because and not inspite of it. Hardly any bugs in production.
In my experience code quality only manages to employers/managers when things break. The only other thing that matters to them is getting stuff out the door so money can come in and new stuff can be built and the cycle can be repeated.

I've had situations where I talked to managers about a situation that would escalate in the coming months, only to have those same managers mad at me when it finally did asking me why I didn't warn them.

I always wonder who these developers are that get time to write tests and develop new necessary skills. But I imagine these developers work on in-house projects, not for clients.

It all depends on the team size and the where the company is at. We're a 2 member team and for all intents and purposes code quality takes a backseat. It's not outright ignored but there are a few shortcuts that i take that will hopefully not bite us. All in the interest of shipping things faster. I end up refactoring code at nights after we've pushed to the app store.

In a previous startup that I worked in code quality was outright ignored and I saw first hand the kind of technical debt that builds up because of this.

A foolish consistency is the hobgoblin of little minds. :)

These kinds of priorities will vary depending on time as they have inside my own little company. I generally like to invest more in quality aspects earlier on the project so that the amount of entropy is limited. As the deadlines loop, corners are cut and compromises made to get the thing out the door.

My employer puts no value on code quality, design patterns, tested code and test coverage. I would not work for them if they did.

I put value on those things, because that's my job. Their job is business. They want features that will enable their job. I expect nothing less. I want them to tell me exactly what they need to get to the next level. How to achieve that is what I do.

If they ever tell me how to do my job, that's when I will hand in my notice.

How to deal with management breathing down mandates wasn't the question. The 'company' in this context represents you and your team.
That sounds nice in theory but it looks to me more like an inmates running the asylum situation.

The company or "business guys" should at least hire a CTO that ensures a baseline level of quality instead of letting the developers roam wild and free :)

Unless you're the CTO, then it makes perfect sense.

I've been with my current company for 6 months now and what I found is the following situation:

- After many years of getting shit done mindset, now maintenance costs are significant, mainly because we can never reject bug reports from customers because we don't know if stuff is really broken. So most of the time, one of the maintenance guys spends hours/days and finds it's a problem with the customers' network, weird proxies, unsupported hardware, whatever.

- As a result, the company frantically started building extensive test suites. However, with most things done in a frantic manner, this doesn't work so well because it was not engineered properly. We have/had hours-long test suites, hard to reproduce failures, devops problems for the test machines, etc. etc. It is, however, much, much better than the previous approach (i.e. release and pray to God).

- Now, after the dust settled somehow, people are starting to realize that the only way to improve the situation is by focusing on quality from the beginning. We spend more time designing architecture with testing in mind, try to be somewhat TDD-ish, look at coverage early on. Now, when a manager is asked to provide estimates for a feature, they are asked if they can fulfill the requirements on time, within budget and in quality.

It takes a lot of experience to be able to write high quality code but I think it also takes a decent amount of experience to know when you should just step away and ship it when code is good enough.

If you're writing a minimal viable product, something that you know isn't likely to be expanded on or code you know is only going to be live for a few months, obsessing over code quality can actually be a really bad thing. I've been on short time scale (you won't always have control of this) projects before for example where continuous integration, code coverage, code reviews and TDD were insisted upon where the extra time invested in these just didn't make any sense.

It's a different story for projects where mistakes can be very expensive or when you know code is going to require maintenance for a long time but I think it's important to learn when there are other priorities. Recognising when you should just "get things done" is actually an important skill that shouldn't be looked down upon because projects only have a finite amount of resources.

Getting things done should be the correct answer for most of the times. All the code quality, design patterns, testing, and automation is done with an objective of keeping the ability to still get things throughout the life of that product.

I've seen horrible overengineered sins being done due to this "focus on code quality" for the code quality sake.

My company exists for the sole reason that another company focused too much on "getting things done". We're a newly founded company that is completely in charge with replacing the engineering departments of our sister companies. Our sister companies have millions of lines code code written over the year. Most of in the most horrible state you can imagine, full with security holes. Our company was brought into existence to clean up the mess and allow the whole organisation to move quicker.

In our own company, getting things done is important, and sometimes we do prefer that over writing high quality code. But that decision is not made lightly and it's usually still good code compared to what it's replacing.

We've been working on replacing a large real-estate website (millions of visitors) with a new version that has been rewritten from the ground up. We did this in 6 months and are going to be releasing on time and within budget. The code is in great shape and we got things done.

that seriously sounds like fun
It is. I doubt you're in the same geographic area, but in case you are, check the link to our company's website in my HN profile.
Sounds eerily similar to the company I work for which was founded because the company tried to build something internally and failed. Our engineers ship a ton of code, most of it good, but unfortunately we've had quite a few problems since we effectively don't do any real testing of the software before releasing to production.
Maybe you should hire some QA people, that helped us greatly :-)
How come this question managed to appear on the top page? Asking this question and expecting a correct answer is bananas. There are so many factors that you have to take into consideration that it is virtually impossible to make a right generalization. The question you should ask though, is: "What should I do to achieve goal that I've set." If your product is unstable, bugs are piling in the backlog - _maybe_ holding the factory line for a refactoring is right - but only just maybe. Remember, that users don't care about how cool your stack is.
Define: code quality

We're focused on getting things done, and I think that is a good focus and always has been more satisfying for engineers to see things ship.

But... there are extremes at both ends of that scale that make for very bad places to work, and really bad product and code.

Getting things done whilst not applying any focus to debt avoidance, maintainability, observability, supportability... is a recipe for disaster that leads to constant fire-fighting and the burning out of engineers and others.

Yet building ivory towers of as close to perfect code equally is a bad signal that can kill a company (not bringing in revenue whilst having costs). Not all code is equal and some code requires a higher quality than other code.

I've found that what experience has given me over 20 years is a pragmatism... is it constructive to add this nice-to-have thing, or would it bring more $$$ in at an acceptable TCO if I just do it sooner.

The best engineers I know all strike a balance; keeping things simpler than a lot less experienced engineers would expect, and shipping something sooner.

> The best engineers I know all strike a balance; keeping things simpler than a lot less experienced engineers would expect, and shipping something sooner.

Yes.

Because experienced engineers know that there is an exponentially-growing cost associated with complexity. So what may look like "clean quality code" at first look may in fact require an entanglement with frameworks that may or may not age well. And when the business needs start diverging with the vision of framework makers, then there's a world of painful molasses as the team struggles to either hack the requirements into the current codebase, or perform a costly rewrite.

My team is currently developing legacy product that was bought from another company, and code quality is what you expect when the team had changed several times already. On one hand, we have immovable deadlines like Steam sales; on the other, bugs in the build immediately impact sales through negative reviews and refunds. So, after seeing so many bugs with our multiplayer, our studio head urged us to spend some time to refactor the damn thing from scratch - while I, the lead developer, has been more cautious about it.
Get things done unfortunately.

Everything is Minimum Viable Product, trouble is those MVPs end up in producation and never actually get rewritten so all code is horrendous when it comes to quality. Result: Even what should be insignificant changes takes forever and you never know if you are introducing bugs due to zero unit tests. Work that should take a day or so takes weeks.

I've seen programs that are just hundreds of lines of code in Main(). variable names like `var varvar`. No DI, code that is very susceptible to sql injection, things like

`var sql = "select * from " + tblName + " where Foo = " + searchString;`

And other horrendous things. No one seems to care though. If it causes an issue in the future (and it will!) that's future developers problem.

The other issue I find with this is you end up going home each day as a developer and feeling completely unsatisfied, you can't take any pride in your work as it's all just a hack job to get it working ASAP. It's like if I trained to be a chef then got stuck in a kitchen and spent all day just heating stuff up in a microwave.

That sounds like a nightmare tbh. I hope you can get out of there soon enough.
Why? I can understand not doing unit tests or taking shortcuts to decrease time to market, but it doesn't take any more time to write "clean code" than unclean code. The code syntax looks like C#, it's a strongly typed language and with a tool like Resharper, it's simple - and my usual MO just to write a quick method to get it done and go back and use automated refactorings like Extract Method, pull members up, Rename variables, Extract class, create object from parameters, etc.
I find most devs won't buy a tool like Reshaper, so if the company won't pay for it, they will never use it.

I love resharper personally and have my own licence.

I mean, I've seen WPF apps where everything was in app.xaml.cs because it was just easier. Need a function, stick it in App.xaml.cs. Need a class, stick it in app.xaml.cs. At this point I think APp.xaml.cs in one our solutions is around 130k LOC because one of the devs thought just having a whole bunch of global functions was easier than worrying about nonsense like classes, ecapsulation, testability etc. You can do this when their is no code reviews. (Who has time to do code reviews, that's going to slow everyone down!)

I've seen console apps written that were all in Main because the attitude was start writing it, debug as you go, almost like writing C# interactively, moving the debug breakpoint up as you make mistakes nad want to rerun stuff. When you can get to the end without it blowing up. You're done. Deploy it.

Or web projects where they say we want you to gather data from some DB, display it in a nice way. It's just a PoC, so knock it up in half a day. It actually though ends up pretty complicated but you get it done in a day or so. But still, the code is a mess but it's PoC. But then the client likes it so this mess gets deployed. Then they want a feature added, but you don't have time to rewrite it so you just have to hack around the initial mess to get it working. Then more features and more features until you have an unmanagable mess that you hope you never have to touch again.

When you're working to half a day / a day for what's a non-trivial project sometimes even naming variables takes a back seat. So you end up with stuff like `var varvar` or `string s1`, `string s2`, `string s3` ending up in your source code.

It's not great, although sometimes it makes me laugh, it mostly makes we think why do I bother though, but that's the reality for some places.

We have similar issues. The MVP concept is taken to an extreme; proof of concepts are created, used, but never iterated on.

I can relate to the last bit too; it also feels bad when you know people are looking down at your "lack of productivity" when you're just trying to slow down a bit to build maintainable software.

It's just my opinion, but as I always see during the years of work if you only focus on "getting things done" you have an illusion that you ship faster.. This way you will have more bugs, regressions, technical debt etc. and fixing them will take much more time than doing things the right way.
Why does gettings things done preclude quality code if you know in advance that you took shortcuts? For instance, write now to "get things done" I might keep all of my passwords for a system I'm trying to get through QA and UAT in a plain text configuration file. Knowing that's a "bad thing", I'm going to abstract how I get credentials in a method/class that everyone uses.

Then once I decide how we want to store credentials securely, we can rip it out, change one method and everyone is updated through the shared library.

Another real world example for us is logging. I knew in advance that we ultimately wanted a better logging framework for searching than just a straight text log like you get with log4net/log4j. We wanted structured searchable logging and to eventually use Elastic Search and Kibanna. I didn't have the bandwidth to do that at the time, but I still insisted on Serilog that would give us structured logging and just used a text file sink, later I added a Mongo sink for searchability just by making a configuration change, when I get around to it, I'll add an ElasticSearch sink. We then get easily searchable logs with applications specific properties to search with a nice front end without any code changes.

Even if I skip unit testing, I'm still going to insist code be structured in a way that separates business code from persistence so when we get a chance to write unit tests (if ever) it makes it a lot easier.

Yes it takes years of experience to know when you are taking shortcuts (getting money on credit - technical debt), and knowing how to get the loan at the lowest interest rate to make the loan less onerous (paying back the technical debt)