10 ms·
> "You see, the leadership did not care about the code quality as long as the stories were delivered on time." My problem with the concept of technical debt is
by hooande 4y ago
> "You see, the leadership did not care about the code quality as long as the stories were delivered on time."
My problem with the concept of technical debt is that "code quality" is subjective, and more often than not it translates to "I don't like the structure of this code because I didn't write it". What matters to the business is that the code works. The owners of the business do not care if the developers enjoy working with the code or if they find it to be well written.
I hear all the time that bad code slows down development, increases bugs, etc. And that can be true in a number of cases. But most of the time it's just complaining. If a developer takes the time to re-factor the code base, it's very likely that whoever takes over from them in a few years will have the same complaints about technical debt and want to re-factor all over again.
The best way to ensure everyone's job and increase compensation is to deliver features that customers really want. Doesn't matter what the code looks like, as long as the customers are happy. Re-factoring is important to developers and to maintaining an organization. But it can wait until there aren't pressing feature demands.
- mistrial9 4y agono mention of language(s), product(s) complexity, age of code, generic code hygiene topics..
- mkoubaa 4y agoThere's always the risk that the people tasked with paying down the technical debt simply drive the code into a different corner. Excellent technical leadership is extremely rare and can make a huge difference.
- posix86 4y agoAgreed until the very last sentence. Refactoring should never happen for its own sake. You should never make code beautiful because it's beautiful. It should be nice to the extent, as you correctly said, that it facilitates creating value, in form of a running program, not as source code. This means that refactoring is worth it exactly if the total time spent to refactor the code is less than the time you save implementing future features after the refactoring. I'm at the start of my career as a software engineer but it seems to me a good rule for refactoring is that it should only ever be done if the advantage can be evaluated in the form of concrete new features being easier to implement. If you refactor the code so that existing features would've felt nicer to implement, or are nicer to read, you've already played yourself, because maybe you get a high of ecstasy because the code that was ugly before is now clean, but as soon as the next feature comes around that you didn't anticipate, it was all for naught, and you're writing ugly code again.
- josephg 4y agoI’ve been programming for over 30 years and I don’t entirely agree with you. I agree that you should make choices in line with what will get the best long term value. Sometimes that long term value is captured by making dirty prototypes that you can learn from. But sometimes you’re working in a codebase which will probably outlive you. And in that case it often makes sense to think of your code base as a garden that you tend. Spending effort making tending the garden delightful will almost always pay off given enough time. And here I’m thinking about things like improving the build process to speed up compilation, adding tracing to make debugging easier, refactoring, documenting the core design and philosophy, and so on. You can’t make Google chrome, the Linux kernel, llvm, or other projects like that by taking dirty shortcuts every time you add a new feature. If you do, you’ll end up with a buggy, unmaintainable mess that is impossible to change without introducing new problems. This isn't just theoretical - look up the story of Toyota's brake problem a few years ago. I've also heard some grizzly stories about software practices at Boeing and Oracle. Good cooks clean their kitchens. Soldiers maintain their equipment. And efficient programmers keep tidy codebases.
- jagged-chisel 4y agoI'm with you. I tend to see little discussion about long term value. "Long term value" includes "making it less expensive to add features." At my current company, we would run in circles chasing the same bugs because of spaghetti code plus competing business requirements. The answer to "why do new features take so long?" was fairly straightforward. We were able to argue for a rewrite partially on the grounds of the speed of future enhancements. During the rewrite, it has been amazing to several team members (juniors, management) at how easy it is to track changing requirements when there's good infrastructure and when solutions are kept simple.
- Supermancho 4y ago> But sometimes you’re working in a codebase which will probably outlive you. This is so rare, it's not worth thinking about. Code lasts a decade or two before it's been completely rewritten or replaced. After 30 years, the oldest code that I ever touched exists in very few places (2 that I know of). > Spending effort making tending the garden delightful will almost always pay off given enough time. What constitutes "good practice" is ever-changing and it doesn't add business value. You work within the constraints of the time and move on. The people who do this find themselves in the best position, career-wise. Paying some small attention to maintenance helps you move up and on to bigger projects and responsibility. Like all things, pursue a middle ground of philosophy. ie You can fiddle with code forever trying to make it "better". More extensible, more maintainable, more clear, more more more. Arguing over future cases (premature planning) is the most common sin. Planning for everything to be reused is not being efficient. Regardless, you have biases that inform what you think is "better" and how software will be used, which future you (and other developers) will note share.
- josephg 4y agoWhat I take from your comment is that it doesn’t matter to business what the code looks like. But it does matter to engineers that they have buy in on the design choices. And that feeling like the code was designed in ugly / foreign ways decreases motivation and productivity. I don’t think that the answer is for engineers to just “suck it up” and wait until there aren’t pressing feature demands (which usually never happens). But instead, we should spend time reading the code our coworkers and past employees have written to understand the design and philosophy behind it. If the design of something you’re working on isn’t good by your standards, your productivity will still suffer if you leave it how it is. Especially if you have good taste. The feeling of deep authorship - like, “this is my garden and I’m proud of it” is something worth cultivating even if you only care about output. I can close way more tickets in a day if I feel at home & in control with a codebase. And that’s something that matters to business as well as the engineers on the ground.
- teucris 4y agoTo address the “I don’t like the structure” argument, I suggest quantifying code quality by how long it takes a new engineer (moving into the codebase or just hired) to ramp up on the system to fix a bug or add a feature.
- pfarrell 4y agoAgree with most of this, except the last segment. I'll add that there are other aspects of "quality" in code. For sure, doing what the customer wants and is willing to pay for is paramount, but there are definitely other things that you want to deliver. * how quickly can you answer questions about business metrics? * how easy is it to identify that bugs are occurring? * how long does it take to figure out what to fix when it's broken? * how much change is involved in fixes (e.g. does a PR fixing an issue touch like 25 files or does it touch just a few files? * how quickly can new employees come up to speed on the code and alter it confidently? * how easy is it to add new features? Now, these things are hard or take time to measure, but those are qualities I look for when determining if a codebase is good.
- ignoramous 4y agoReminds of this article from athenian.com which is a pretty good read on velocity and quality as a team / product org scales from 5 to 20 to 100 to 250 people: https://archive.is/FQKJH https://archive.is/FQKJH
- pfarrell 4y agoThanks for that! I've signed up for the newsletter based on how good that article was.
- clnq 4y ago> I hear all the time that bad code slows down development, increases bugs, etc. And that can be true in a number of cases. But most of the time it's just complaining. If a developer takes the time to re-factor the code base, it's very likely that whoever takes over from them in a few years will have the same complaints about technical debt and want to re-factor all over again. You need to measure these things objectively. There are several ways to estimate technical debt, like asking system owners how long their teams would take to bring their code up to a list of standards. The time estimate alone is an excellent tool to measure the scope or remediation cost. But there are also several more aspects to technical debt: transmissibility (how likely it is to spread), remediation competencies (does the team have the skills to remediate it), maintainability (how much does it cost to maintain this case of tech debt over a month or a year), attributed bug count (how many bugs are linked to this instance of debt), and so on. Refactoring code just because someone has complaints is an indolent and unsurprisingly ineffective way of maintaining it. As you say, opinions about how code should be written are a dime a dozen. The shortcomings of a particular system need to be meaningful and clear before they can be assertively fixed. They can be generalized, like "this code doesn't follow patterns that would optimize it" or "this code has had too many hotfixes and is now causing many bugs", or precise, like "cache misses here impact systems A, B, and C severely". But they still need to be clear and business-oriented. Then tech debt repayments can be very effective. I have seen bugs attributed to a system go down by 90%+ after a short refactor when it was carried out effectively. Investing into systems that prevent tech debt in the first place can also be effective, but it likewise has to be done in a measured and targeted way. If teams tend to make mistake X, then you can often deploy code analysis or submission tools to identify that mistake and reject such code. Over a project's lifetime, you may write hundreds of such code validation tests, but in teams of 100+ people, they can prevent a tremendous amount of work resulting from tech debt. In short, it is a mistake to dismiss the tech debt problem when one has not put in the effort to tame it or has gone about taming it in a lazy, wishy-washy way. If the team has particular code quality standards illuminating tech debt and allowing the coders to target it clearly, it can be remediated effectively.
- xvilka 4y ago> "code quality" is subjective There are objective parameters like: tests coverage, how many bugs you have (or were fixed) on from the static analysis, presence of periodic or constant fuzzing, portability.
- linuxftw 4y agoStrongly disagree. I write a lot of go code, and poor quality code introduces a lot of tech debt because it's un-testable. So, if you want to write basic unit tests, you can't do so easily without refactor large chunks of the code base. So, if you've already shipped a feature and need to make some kind of change, you can't do so with any confidence. Implementing unit tests to validate you're not breaking existing functionality is impossible, so you need to refactor, which introduces extra risk.
- jahewson 4y agoSort of. But customers don’t want features. They want you to solve their problems. Most customers also value that being done reliably. So features are a means to an end as much as code quality is.
- iopq 4y agoNot really. When each PHP page was copy pasted and slightly modified, I had to manually search to fix each bug and fix it in EVERY instance. Are you going to tell me that this kind of tech debt doesn't affect my time to fix the bug? I could have done it once, now I have to hunt for 5+ instances of it. Am I just complaining or did doing the original development in a lazy way directly impact my time to complete the task? I could have recorded the exact amount between the original bug fix and finally fixing the last instance of the bug to quantify how much time lazy coding cost me. It may have taken the same amount of time to write the original pages with an extendable component that only has one copy and takes arguments to create all the variations we need. But in the end we'd have fewer lines of code to maintain in the future and that's also an objective metric.
- hamandcheese 4y agoOn the flip side, change is far more risky when it affects many callers rather than once page. Whatever time you “wasted” fixing multiple pages might be instead spent validating that the single fix doesn’t produce any unintended consequences. Simple duplication is probably the least bad form of tech debt I can imagine.
- iopq 4y agoYou have to test all of the affected pages anyway the real horror is they have slightly different version since they already had other changes done to them, and I have to understand whether I should merge the functionality, keep it different, etc. when I have multiple callers it's going to be the same unless you pass in an argument, so that change is self-documenting since it signifies intent
- resonious 4y agoI think it's pretty easy to come up with a counter argument like "hey what if I want to change the code for this one page and not the others? well, good thing each page has its own separate code!" If the code in question was shared, this person would have to spend time thinking about whether to add a boolean flag to the shared function, create a new function, or what-have-you. And I can see other comments here saying that boolean flags are also tech debt. For your scenario, I completely agree that the decision to not share code lead to you spending more time. We can be objective about time spent for specific scenario A with codebase B, but we cannot enumerate all scenarios and all codebases and so it's quite hard to ask what's the expected value for "damage done" by a particular style of programming.
- pixelrevision 4y agoI think the problem here is that there are very few places where there is any time between pressing feature demands. This always seemed to me what the agile guys were saying. The approach was all centered around the idea that things would always be changing and pressing. The only way to combat that is to put constant refactoring into the day to day so that your codebase can remain coherent and productive to work on. The bonus of doing things like this is that if you are constantly changing your code then it becomes battle hardened to accept change. This gives you better ability to keep up with the changing demands of both customers and technology.
- amalcon 4y agoI'm mostly with you, but "it can wait until there aren't pressing feature demands" actually means "it won't happen until something completely breaks and it can no longer wait." There are always pressing feature demands. There are some things that are not just annoying to deal with, but actively impede development or encourage further hackery to make them manageable. Those things need to be fixed at some point, or there will be a real cost.
- dsugarman 4y agoHit the nail on the head. I think it's actually a bit worse on the refactoring, yes the next snooty Sr engineer you hire will say you did it wrong. The bigger issue is that working on "technical debt" actually introduces bugs and decreases stability because you're wholesale changing out battle tested code for theoretically better code. Your customers will not thank you
- deleted 4y ago[deleted]
- jagged-chisel 4y ago"Code quality" should be about readability. And by "readability" I mean "can the function/module/system be understood by the individuals on the team fairly quickly?" Just because someone doesn't like the indentation, or the looping style, or whatever opinions they have ... these things don't make code quality poor. If you can understand the system, make changes, and add features without bringing down large parts of the system, it's probably fine. The problem as I see it: companies prefer the inexperienced devs because they're less expensive, and as a result, their inexperience leaves them frustrated with code that they "don't like." They then attempt to sell management on a rewrite on these grounds. The team can only deliver features that customers want, on the schedule the business wants, if the underlying infrastructure of the code allows it. If the code infrastructure forces me to spend too much time implementing features, and feature requests continue pouring in, then there will never be time to refactor because there will always be "pressing feature demands."
- bcrosby95 4y agoI heavily disagree. At the time of change, its obvious you're making the code shittier. That function? It doesn't do what it says anymore. That other function? Just a few more boolean variables. Hey, we don't need to refactor, we can just make negative numbers mean one thing, and positive ones mean another! Death by a thousand cuts. This is also the best time to refactor. You skip the whole "I don't like the way the code looks" bullshit. The codebase doesn't support your feature? Make it support your feature, then code your feature. And you know what else? You are only changing code you're touching. Refactoring code you don't need to otherwise touch is a waste of time. But yeah, if you parachute in 6 months later to look for a refactor, its gonna be all gravy. How much shittier your code is just a distant memory. Get on that next feature - just another flag, just another lying variable - in hindsight, it's all subjective anyways.
- monocularvision 4y agoI consider “code quality” in our codebase to largely be defined by “does it follow our opinionated architecture?” If the answer is “No”, it can be difficult for others to understand. Reworking that code to follow our architecture generally makes it easier for us all to follow. One might need to not follow the architecture because it doesn’t handle something new to the app. When that happens, we try, first, to update the architecture to be able to handle the requirement and then implement the feature. But if that isn’t possible, we plan to clean up the debt as soon as we can after shipping. Overall, it has worked remarkably well for our team and has led to what I consider the “cleanest” code base I have ever worked on. But it is dependent upon us having a shared understanding of how we implement features.
- moris_borris 4y agoThe miracle of a clean code base is that it means some programmers got together and agreed on a bunch of things.
- tatersolid 4y agoI’d think it’s the opposite: clean code indicates 1-2 opinionated individuals built it. Committee decisions are almost always overly complex compromises with too many special cases. See most RFCs, IEEE specs, congressional bills.
- quanticle 4y agoDoesn't matter what the code looks like, as long as the customers are happy. Can you imagine if other industries had this same attitude? "It doesn't matter what the warehouse looks like, as long as we ship on time, and the customers are happy." At one level that's true, but at another level, it does matter what your warehouse looks like, because a neat and tidy warehouse is what allows you to ship on time. A warehouse that's filthy and disorganized is one which loses orders, ships the wrong products. Similarly a disorganized codebase with poor abstractions isn't bad because it's unpleasant to work in. It's bad because when a dev ships a feature, they have little or no confidence that they've done so without breaking two or three other features and causing customer dissatisfaction in the process.
- WJW 4y agoHave you actually been inside many warehouses or factories? I don't think I've ever seen one that was as clean or visually attractive as the areas that customers were meant to see. You're right that they're (usually) not filthy to the point that it impedes operations, but it's quite correct that customers don't care about how the warehouse looks like as long as the goods arrive on time. Same for restaurant kitchens, bakeries, metal workshops and a host of other production facilities. The only production facility I've ever seen that was "clean" was the assembly area of a medical instruments producer (it was a literal clean room with suits and everything), but even their warehouse did not look attractive. Their customers were quite happy though, the company was growing fast. Most programmers imagine other industries to be better because they only see the customer facing parts, but that is like judging the state of a codebase by how nice the landing page is styled. Penny-pinching managers exist in all industries.
- quanticle 4y agoJoel Spolsky has a good article about this [1], where he discusses apparent cleanliness versus actual cleanliness in the context of a bakery. I agree that, at least on the surface, a warehouse or commercial kitchen may be quite messy. But there has to be an underlying order, otherwise the system just doesn't function like it ought to. [1]: https://www.joelonsoftware.com/2005/05/11/making-wrong-code-look-wrong/ https://www.joelonsoftware.com/2005/05/11/making-wrong-code-...
- jack_h 4y agoThis attitude exemplifies McNamara's fallacy.
- bbojan 4y ago> What matters to the business is that the code works. Yes, but there is a time dimension to "code works". It should work tomorrow when a new OS comes out, and it should work when a library is updated because of a vulnerability, and it should still work when a new feature is added, and it should still work with a 100x more users. The only way to make sure code still "works" in these situations is to continuously keep modifying it. And here the technical debt comes into play.
- Lutger 4y agoCode Quality is not subjective. If some improvement really is, then its probably not a code quality improvement. The ability to reason about it or even measure it might be subjective, in the sense that most developers aren't really good at articulating quality. Also, developers often confuse familiarity and quality, or to be a bit more generous: are unable to accurately assess quality of unfamiliar technology. Furthermore, there is also a widespread misunderstanding that if you can't 100% prove something beyond a shred of doubt, that any position is as arbitrary as a favorite color and any reasoning a waste of time. > Doesn't matter what the code looks like, as long as the customers are happy. Customers being happy or not is exactly the problem of Code Quality. When a system breaks down over time due to a pervasive neglect of quality, the customers won't be happy. In practice this is happening slowly over time. Your lead time increases, there will be more bugs and changes will cause more problems that are increasingly hard to overcome. It can also come as a collapse, for example a huge outage, data loss or security incident. This can kill your business. Quality is not something done for developers sake, it is about the ability of making customer happy over time rather than just now. That is the ultimate justification, which isn't subjective, and the source of legitimacy of any time spent on refactoring at all. If it is not ultimately rooted in solving a business problem, then it is not a quality improvement at all. And yes, sometimes developers try to masquerade personal taste as quality (refactor to something I know or like), and in these cases the outcome often isn't an improvement at all. In fact, it is often a regression. But that doesn't mean quality improvements aren't real or beneficial.
- Nomentatus 4y agoRight. I remember a very small non-profit that was so happy with my code the owner wouldn't let me fix a bug (lack of a fail-safe), having convinced himself it would never be a problem the way the software would be used. Despite the fact I was working for free. Two years later, someone else was assigned to use the software, and that "bug" incurred a phone bill that killed the non-profit outright, as I had predicted could happen.