Hacker News new | past | comments | ask | show | jobs | submit login
The Carrying-Cost of Code: Taking Lean Seriously (2011) (michaelfeathers.typepad.com)
68 points by mpweiher on June 16, 2018 | hide | past | favorite | 18 comments



This is my life as a lead dev / architect. Deleting code and structuring the code so that parts of it can be deleted. I actually tell people who ask what I do: "I spend my days removing code."


I don't know about "forced" deletions, but I actually feel deleting unused/old/crusty/etc.. code is cathartic. I don't need any pressure to do it, am I alone on this?

Also, I have some awesome code I wrote over 10 years ago, and I wouldn't dream of deleting it. There's moments where you make a decision on something, and years later you look the code and say "Who wrote this? This is great!" oh wait...

Code as inventory almost goes hand in hand with coders and machines or assembling line workers. I don't think this is a good direction to take.


I do think that, in my experience, most organizations don't think the amount of code they already have written, is a thing they need to minimize or even track. Yet, most organizations are limited in their ability to develop, by the amount of already existing code that has to be understood and maintained. The usual attitude seems to be that "it's already written, we don't have to pay anything more for that". The idea that existing code, the sheer quantity of it, is a drag on an organization's ability to write new code, was not clearly understood in any place I've ever worked.


Would you say that the larger the organization, or perhaps more accurately, the further a developer is separated from "owning" their code, the worse this issue is?

In my case, if my code causes a bug, I have a very few steps between the person reporting the bug and the complaint getting to me. It feels personal.

Your suggestion seems to imply it's just money, but how do bean counters effect ground level code decisions in an organization?


I think that, it's not money per se, but as you say the number of people between the developer and the decision maker. The only person who perceives the problem of having too much code, is the developer (and then only sometimes). Organizations do well at optimizing what they track, in many cases, but they don't track amount of existing code as a negative thing that needs maintaining, so they don't do well at optimizing that.


I find myself optimizing a lot of the features I write for ease of deletion. It keeps the codebase very loosely coupled and makes cleaning up dead features, or rewriting them, easy.


If you have time, do you mind sketching some concrete examples of how this works? Do you find structuring code to be easy to remove is to the detriment of anything else?


I follow this design methodology https://github.com/testdouble/contributing-tests/wiki/Discov...

It's focus is not on constant refactoring but constant rewriting. Turns out easily rewritable code means easily deletable code. I think the major drawback of this approach is it's hard to follow for systems where you don't yet have some kind of intuitive sense of how the low level implementation requirements since you end up leaving those for last.


thanks for sharing your experiences and the link.

makes sense. i guess in my limited experience trying to unit test existing code that's a gnarly mess, as you gradually rewrite it to decouple dependencies and isolate accreted responsibilities into single-purpose collaborator objects that can be dependency injected, and generally get rid of as much global mutable state as possible and replace things with genuine functions, you end up with something that's broken into components that can be easily constructed and tested in isolation. i can understand then how it would be easy to delete some of those components. (not saying your approach is exactly the same as what i am describing here).

re: the link

> While code reuse has been commonly promoted as a universal good over most of the history of computer science, it comes at an increased cost of change & replacement. In order to rewrite a bit of code, one must ensure the rewrite will satisfy its contract with all of its callers.

yes, i can totally appreciate this. i've been on projects where not-very-technical management suddenly decides it wants to focus on reducing the amount of code duplication, as that's a goal and metric that can be talked about while only having a superficial understanding of what's actually going on in the codebase. for codebases with swathes of low-quality code and poor automated test coverage, trying to couple everything together unnecessarily for the goal of "code reuse" can turn out to be a nightmare: a lot of previously unrelated components without solid regression test coverage suddenly depend upon some poorly designed bug-ridden common dependency with a broken abstraction that is constantly getting patched by developers who are touching one or more of the leaf systems that depend upon it.

to quote a pithy line from http://quotes.cat-v.org/programming/

> Before software can be reusable it first has to be usable.


In the job I just left, we were asked to define metrics upon which we'd be evaluated at our yearly reviews, and in my last two years there I chose, for one of the metrics, Lines of Code Deleted [without negative business impact, e.g. breaking features that customers relied on]. This was in an organization with crippling technical debt.

As far as I know I was the only one in the org to do this, and, while I thought initially that it was a slightly outrageous metric, I now believe that if every engineer had taken it upon her/himself to do the same, starting just a few years ago, we'd have wound up in a significantly better place business-wise today.

A corollary to this approach is that Choice of Language Matters; all other things being equal, you should use tools and languages that give you the same functionality with less code.


Is anyone going to seriously talk about how we can treat code as inventory? How can we continuously reduce inventory?

His idea around three month time based decay on code doesn't seem that feasible to me.

Perhaps what we need is a fixed complexity (LOC and other metrics) target where we're not allowed to exceed that unless specific reasons come up.

100% code coverage is probably another thing that might help reduce dead inventory.

We also can measure what code actually gets used in production, and delete anything not being used. Could even automatically delete code based on lack of usage, and even delete the corresponding tests.


That once-a-quarter rare bug handling code is not going to fare well with automatic deletion of code that doesn't get exercised in production.

In some domains, I've heard of up to half the code being code that handles rare conditions.

More importantly than removing mature code, it seems to me that pieces of code that are in use and haven't changed in a while are good candidates for applying formal methods.


I think the problem is that "code" straddles this very thin line between technology and operations. The value of technology is that you can solve a problem and perform it more effectively essentially indefinitely. Operations are much more fluid; the most effective way to run operations changes constantly and evolves over time. I think a lot of our time is wasted trying to capture operational logic that is unlikely to persist over long periods of time, and that's where some sort of code decay mechanism would he useful. But the flip side is that occasionally your code will encapsulate something more technological, a solution that addresses a core function of your business or whatever other problem space, and then you have code that you absolutely 100% do not want to decay. I'm not sure there's any clear mechanism to distinguish between those two things. Your idea of scanning code that runs in production might be a good place to start, but plenty of pseudo-dead code (logic that ought to be decayed but manages to run anyway) will probably continue to accrue.


It's only really fair to think of code which is tied to features or bugfixes which haven't been released yet. The reason why inventory is a problem in Lean is because it represents spend that hasn't been repaid with revenue, once you ship the code then it's shipped.

Within the Lean model, I think it makes more sense to think of code as something that "weighs down" the different stations in the factory, making them less efficient, like unmaintained workstations in a factory that slowly break down. If you have a station in your software factory representing API changes, then whether or not you have a pile of half-completed work waiting for API changes has little to do with how quickly you can make changes to the API - that's determined by how many changes you've made before.

It's much easier to delete code if you're allowed to delete features. And it's much easier to delete features if you have a clear deprecation and EOL policy, an easy way for customers to determine if they're affected, and simple means of migration.


When I was a new developer it was all the rage to use static analysis tools to calculate cyclomatic complexity.

There were even processes that required justifying branches.

Unsurprisingly people just turned to patterns that masked the cyclomatic complexity from the tools.




I find it odd that people in 2011 didn't know about Git blame. Or have the ability to simply script the tools they were complaining about not having.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: