Hacker News new | past | comments | ask | show | jobs | submit login
Theory-building and why employee churn is lethal to software companies (baldurbjarnason.com)
622 points by bwestergard on Jan 10, 2023 | hide | past | favorite | 420 comments



> Documentation only works up to a point because it can both get out of sync with what the code is doing and because documenting the internals of a complex piece of software is a rare skill. A skill that most developers don’t possess. Most internal documentation only begins to make sense to a developer after they’ve developed an internal mental model of how it all hangs together. Most code documentation becomes useful after you have built the theory in your mind, not before. It operates as a mnemonic for what you already know, not as a tool for learning.

This is ringing particularly true to me right now.

The organization I work for has allowed bit rot to occur for a number of years, to the point that it's becoming increasingly common for things to break whenever even seemingly small changes are implemented.

The "solution" that we've implemented is to require a detailed RFC document whenever you want to create or modify anything. You're required to outline every anticipated step along the way, all the tiny minutiae that you foresee yourself encountering and how you'll deal with it. And in a Google doc, no less.

It's utterly exhausting.


I worked in an environment where a senior architect got to veto every major effort that I publically made to improve the structure and maintainability of the software.

At some point I got so pissed off about this that I started assigning code reviews to him - he contacted my manager and asked that I stop, because he had no understanding of the project in question.

What did this mean from the documentation side?

I would have loved to accurately document what I was doing and how the project was structured - but I actively avoided doing so.

Every time my manager's boss knew what I was doing, I was about to be shat on from great heights.

Months of work and planning erased at the drop of a hat - time and time again.

Dependency injection? Fuck off. Spring's too heavy.

Modularity? Fuck off. The project's too small.

Hierarchical profiles? Fuck you, keep using a properties file (with an increasing number of dynamically generated keys).

I was constantly asking for a new developer to be brought in for the transfer of knowledge - at best I was told "That's not a bad idea."; yet nothing was ever done about it.

I took an unmaintainable pile of bugs and made it stable and maintainable. But nothing I ever did meant that I was someone worth listening to.

Eventually I got so burnt-out (and consumed by feelings of uselessness) that I walked away without finding another job.

I was damned near suicidal from fighting for acknowledgement.

I cannot imagine that my departure went too well for them.


Well, FWIW I have to use all the things you were proposing. However I find them eminently crappy and if I were in a position at my workplace to reject them I would have absolutely done that.

> I took an unmaintainable pile of bugs and made it stable and maintainable.

Same here, except it was supposedly using all best practices e.g. Spring Boot, DI/IoC, Mock testing framework, YAML configs, extremely elaborate package hierarchy and so on. The only thing it did not have was working solution for the business problem it was written for.


Are you me? Our services with all the best practices are also the worst to work on because the business value is hidden in layers and layers of indirection, abstraction and nested packages. It’s like someone took a recipe card to bake a cake and wrote each word on a single page (because god forbid we ever repeat ourselves) and then abstracted away a function behind a series of factories and interfaces that will join those pages with string, and now each word has a single context-less definition so we can tick the “S” box in SOLID.


Hahaha, everyplace everywhere.

I think two things play into this: Layers.. it is just easier for people to add layers around something, not touching and understanding the original code and doing it right there. And then profs or someone else always says layering is good! (It may sure be, or also sometimes such "hacks" are the right thing to do, but if that is always the default mode... uhh oh).

And second, university training: OOP, design patterns, software layers, all claimed to lead to structured good programming automatically still taught in 2023, which is just not true. By untrained or unexperienced personnel leads to worse than 80s spaghetti code..

Just yesterday I exercised with relative who is in university for exam.. Java, design patterns, arggh. Imo it just makes no sense at all to try to teach students inheritance and design patterns with Cat/Dog/Animal et al, it is so backwards. You need to program for a while bigger real systems to see some patterns emerge and their usefulness, and then can relate to the formal way and maybr use some patterns reasonably. But starting with those on toy examples just leads to what you describe: People going in with their trained knowledge and applying that to everything without rhyme or reason. What could be a simple five liner function already becomes a convoluted abomination. Just one concrete example, but this then on many levels of software engineering.

Who or what will save our future? :D No, it won't be ChatGPT. (Second lol btw, relative really showed me how likely all of then may use ChatGPT i. their online exams...)


Probably the mainstream adoption of functional programming, if anything can save our future.

Most people do not have the memory span to work with mutable state, so something simpler should be the default.


I'm not too hopeful. In my experience, functional programming adoption is divided into two categories:

1) Proper FP languages with good enough semantics and necessary features to write functional code effectively. Those languages all fall into category of "too difficult" for the majority of industry, which seems to suffer from severe allergy to learning anything beyond "Intro to programming in Java 6" freshman class.

Even things like lambdas only recently stopped being too complicated for a typical programming shop that follows well-known best practices, such as "Programs must be written for inexperienced non-programmers with no prior exposure to the problem space to read, and only incidentally for machines to execute.", and "Would somebody think of the juniors?". Closures? Nah, the zeitgeist is still on the fence with this.

Yes, I have a sore spot for this. I've heard this reasoning many times in real life, and once was even target of it - an otherwise competent programmer and a good manager once asked me to stop using lambdas for event handlers in Java 8 (which the company had only recently adopted), for the sake of the juniors who won't understand. In fact, he meant specifically his favorite evergreen junior (who's been in that company a couple years longer than I was then). But guess what, couple juniors actually asked me to explain the how-and-why of lambdas to them and got it near-instantly. Said evergreen junior probably spotted the lambdas in the codebase too, or otherwise got interested in this, read up on the topic independently, and three months later was evangelizing basic functional programming in Java and otherwise upskilling his fellow coworkers.

But yeah, it's too difficult, your co-workers won't understand. Anyway, where was I? Oh right:

2) The other, arguably larger, kind of FP adoption: library-level and code style level implementation of FP features in languages with little or no natural support for them. This doesn't mean people understand FP extra well - they're barely aware of it at all. But every now and then some library gets popular - say, a sum type for error handling (typically known as Result, Either, Expected, or something similar) that's "obviously" "better" than exceptions. Except, that library is doing a half-baked implementation of a concept (e.g. monads) that doesn't fit the language, and the users don't understand what the approximated concept is, nor are they supposed to try (remember, FP is too abstract for a freshman after "Java 6 101" class).

The result is, as expected, an ugly mess in the codebase, displaying all the bad sides of imperative and functional styles, and leveraging none of the good sides.

Anyway, what is my proposed solution to this? For the industry to stop hating education and professionalism. To embrace the idea that the job of a junior is to learn, not to be the yardstick for complexity of the codebase. To encourage a culture of learning, of professionalism, at every level. To stop dismissing or banning techniques that reduce size and complexity of the codebase by large factors, just because one has to invest a couple hours of learning up-front to be able to use them. Etc.

</rant>


I’m with you: the problem is that Java and so forth are seen as simple when they are in fact INCREDIBLY complex.


The one thing agile is aimed in the right direction about is that software is for users. Users use it to create value in a business context. Many developers are too far removed from value creation and making sure their features and design changes will actually benefit users in the long run. Tech debt is a thing, but so is business value driven development that works well for users. All of these refactoring side treks need to really be necessary. I do greatly empathize with grandparent, lack of being seen and acknowledged really sucks. And who knows what their situation really was like.


Let's be clear on who the users are, then. In general, I see several different broad groups of stakeholders:

1. The developers who create the software.

2. The rest of the company developers work for, and possibly other people in other companies - who all make money selling or renting the software.

3. The actual users stuck with the software.

I'm not sure if Agile meant 3 > 1 and 2, or just pretended to, but actually meant 2 > 1, but your comment does read as advocating for 2 > 1 > 3, which is arguably the current industry standard.


In the case of Spring what I wanted was adequate dependency injection.

I was dealing with having to support releases across multiple historical branches, and wanted to separate the core and business logic to allow for easier support on the older branches.

I needed the dependency injection in order to break up cyclic dependencies across modules (without which the core and client logic could not be broken into separate repositories).

Internally, the deployment tooling treated the profile as hierarchical; when I took over the project it was already using dynamically generated keys to store trees of data in the .properties files it was using for user profiles.

It only became more hierarchical as time went on and the internal representation fully so - using a tree structure internally allowed for very clean subtree selects (which helped to clean up an entire class of bug, introduced on mass, during a particulary ill advised (and strongly advised against) piece of work (completed (despite being given without notice) in a single iteration - when it really needed at least 2).

I would still have preferred to use an external format that allowed me to specify or generate schemas for the user profiles, and it also would have helped with supporting profile versioning (which would have been valuable for company internal users).


Here's the kicker, I hate to say it, but they probably didn't notice you left.

That's the thing about places like that.


I was the main developer on the single most critical deployment tool in the company.

My departure would've been less than ideal.

Either way, the company's haemorrhaged talent (now including long term CEO and long term CTO) and the stock price has plummeted since I left.

(In no way am I crediting myself for this; at best I was a canary in the coal mine - but I take my solace in schadenfreude.)


Software companies with sufficient market share take on an almost zombie like quality. No matter how much damage they take internally they are able to continue lurching forward and making money because there is no one else in the space that is a viable option or they have their customers locked into expensive contracts. I worked at one such company for a few years. It was terrible. The software was garbage and management was truly awful. We were required to hit 10 ticket points each week or pipped. The only way to do so was to work 60+ hours. I got pipped for the first time (~18 months in) when during the first month of covid lockdowns I got 8 instead of the required 10 points. They literally could not understand how I might have distractions going on due to a brand new pandemic, my kids and wife suddenly being home and lockdown.

Whatever decision you made they yelled at you. I got yelled at once for not lying to a government official. When I quit, every sr. developer quit within 3 months of me; 7 total left and left behind 6 non sr. devs. This was 3 years ago. The company is hemorrhaging money but just keeps issuing more stock to stay afloat. It used the money from that stock to buy its competition in a very niche market and essentially just put them out of business. So they survive and lurch on.


> Software companies with sufficient market share take on an almost zombie like quality. No matter how much damage they take internally they are able to continue lurching forward and making money because there is no one else in the space that is a viable option or they have their customers locked into expensive contracts.

/Softwarecompanies/Some companies/g

I wrote a paper for an assignment (maybe ten years ago, ask me for a link, and I'll see if I still have it), in which I called this phenomenon Corporate Inertia, and it isn't only applicable to software companies.

Sometimes the inertia is good - it allows the company to weather bad times.

Other times the inertia is bad, because the company cannot pivot in time to address new challenges or take advantage of new opportunities.

Mostly, the good outweighs the bad - if a company cannot pivot in time because it is so large, it merely buys the smaller company that verified the idea already.


I’ve always described this as “Rome didn’t burn in a day.”


> Software companies with sufficient market share take on an almost zombie like quality.

+100.

Booking.com and JIRA come to my mind as good examples. Just about everyone complain about Booking, customers, engineers working there, hoteliers etc., Yet it continues on. I hear they've been trying to migrate to a modern tech stack for years but to no avail.


Because most of the competition manages to either be worse than them, or lack the features that actually make them relevant.

I am reaching 50 years old and am yet to see any ticket management system that is as powerful as Jira, while offering a relatively good usability story, and the integration story of having a ticket bind to documentation on confluence, SCM related history and CI/CD reports.

Likewise the competition to Booking usually fails to show as many properties, have as rich filter selection, and in many cases their prices are higher than what Booking offers, moreso if one happens to have Genie level status.


Saying this as not a jira fan but realizing it has its place.

The irony of jira is the years it takes to realize how few pieces of software can soak into complexity like it can.

The pain of jira is how it largely can’t universally handle complexity out of the box or how you’ll find yourself in it - how it must be actually setup for your use case - how much it benefits from being setup by someone who has experiences with the pros and cons of cocaine one of the many ways of doing something.

The new project type (team?) is a step forward to start with from scratch. But a kiss of death if you need to outgrow it for some features that aren’t there yet.


Work management is a custom problem, that no generalized solution will fit.

Unless you're a mega corp - you're not getting a good work management solution.


> We were required to hit 10 ticket points each week or pipped.

I ask about ‘points’ in interviews, its an immediate stoppage for me


Yes, that's very important. I made the mistake of taking a job where they were into full blown "planning poker" nonsense. It was hell. "Is this a 2 or a 3?" The discussion could go on for ages. "This can't be an 8! Can we break down this into a 5 and a 3 point ticket?" No estimate was allowed to be an 8. I better stop, since I'm having flashbacks...


Hah I got in trouble once for just going through a grab bag of bugs from our designer (mostly trivial CSS issues) and fixing them. My manager got upset because the tickets never got their costs estimated, and I never put them in jira. (Even though the “3, 5 or 8” conversation would have taken more engineer time than just fixing the bugs directly).

I asked him why he was so upset. Eventually he admitted that closing tickets in jira was how upper management measured how well our team was doing - and by extension him. I thought that sounded like his problem and still refused to put the issues in jira. So he did it - meticulously creating a couple dozen issues, making up a BS point estimation and closing them all as complete.

Whenever I think about bullshit jobs, I think about those silly cost estimation cards, that guy, and how deeply satisfying it was that day just diving in and making our product actually better.


Tickets can also be some documentation about why some code is why it is. Put the ticket number in your commit message and use git blame when you want to understand something better. By fixing code without tickets you make this impossible for future developers.


Yes tracability etc... but to be honest: For such a trivial thing, this thing called commit message right before or after the ticket reference can do the job as well with one less indirection ;)


This is any-benefit thinking.

There is some tiny marginal benefit to what you’re talking about (there’s a chance someone might later want to look at the corresponding issue). But you aren’t acknowledging the cost, measured in my sanity making a bunch of one-line issues in jira, and the team’s time doing cost estimation.

It’s nice to leave breadcrumbs for future code historians. But our job is shipping product. Cost estimation, jira, etc all only have value proportional to how much they help us ship. If the meetings are pointless, and jira isn’t needed then doing that anyway is a waste of time.


“Link to a ticket system” is generally awful advice.

- Why the commit was made should be in the commit message

- What the change is inherently lives in the diff

- Why the code is how it is should be in comments adjacent to the relevant code item.


To be fair if the fixes are trivial they shouldn't need any extra context from a ticket to understand


I remember the endless Scrum meetings where we debated points with all the seriousness of medieval monks discussing how many angels could dance on the head of a pin. As a rough heuristic points aren't bad, per se, and they are a bit better than straight time estimates.

But when they become the subject of endless meetings it's a tell that maybe the company has hired too many people too quickly and is in the "bullshit jobs" phase where it's happy to waste precious salaried hours on meaningless debate.


Quite standard in any big corporation.

You're lucky not having been discussing money budget per ticket instead.

I have had projects where sprints got money budgets assigned to them, which divided by the cost per hour of each developer got us the amount of hours available for the sprint.

Those hours were the budget for the sprint, no more no less, better chose wisely the stories that fit in.

To make it even better, some project activities only were given such kind of budgets in specific times of the year, then one of the external consulting partners would have the go at that specific sprint.

So not only were the tickets chosen to fit the budget, every few couple of months, the teams doing the work were always rotating.


Hmm every job I have had uses points this way. I find points discussions particularly mind numbing and have no love for them but I also can see the utility. What is the alternative?


When it ceases to be a useful tool to stay organized, and becomes a burden, it's very frustrating. The alternative is to use the tool when it helps you and ignore it when it's not.


I guess it depends on the clarity of the work and quality of the facilitator.

I have had your experience with poorly organized PM and horror stories during sprints...

And I had the best planning sessions with a proficient PM, that made picking up tickets a marvellous pleasure.


What is the exact Q you're asking? I'm genuinely interested.


I ask about development practices, I have them describe how they approach features, tech debt, planning, attribution, interruptions, and so on. Somewhere in there Ill ask for an example and ask some precise questions and then also about points, so they dont think Im overly focused on that exact aspect


> and the stock price has plummeted since I left.

that describes pretty much every tech company in the past 18 months ;)


yarg was holding together pretty much every tech company.


I do wonder at the extent to which I am the manifestation of a charicature of the burnt-out developer.


Yarg owned left-pad.


I have been in places like the one you talked about. I also almost had a breakdown because I used to care too much. After that I had an epiphany, now I only care if others care. Its good for my mental health.


I got hired by a company. First day I found out I was the entire IT staff. They had lost everyone else. For good reasons. Infrastructure was completely failing.

First week was rebooting servers at random to try and get things working while I mapped everything out.

Eventually rebuilt everything and put together a good team.

Key was learning to tell management no. And having someone to keep upper management off our backs.


yeup. and realizing that is the only way to stay sane.

nobody will care if you leave, nobody cared about the last person that left, they have other priorities and software engineering is not one of them.

if its that much of a problem, their business will fail and some other business that does care will take over their market. but that might take decades because software engineering isn't actually core to a lot of business activity. youd be amazed at how bad some software is for major companies, and yet they are very profitable.

you only have control over yourself not other people.


my company's primary app/digital portal that is meant to eventually replace the bulk of phone center operations requirements is hilariously bad after years of development. I used to tell the app team daily everything that was wrong with it in great detail from a usability standpoint of both our internal operations and our external customers but they just took the chat tool down, lol. they've been slowwwwly adding new functionality before the core functions are fully baked and actually useful which is just crazy to me. if it weren't for top management pushing our sales teams to push our customers to use the platform, 98% of our customers would prefer to just pick up the phone and call us anyways. (this is the concrete industry, so not exactly tech forward)


Bold of you to assume that anyone else there has the necessary knowledge to take on their role.

I was in a similar situation once, I spent months telling management that I was the only one keeping them afloat technically and that it was a critical risk to the business. They responded by trying to pressure me into unlimited unpaid travel and overtime.

I left and they fared poorly.


GP learned a valuable lesson; it’s just a job. Don’t tie your identity to your code.


I hear your frustration. I can relate. But this:

> I was damned near suicidal from fighting for acknowledgement

I sincerely hope this was hyperbole. Please don’t ever allow anything work related to affect you to this extent. You are more than your job. There are other opportunities. There is much more to life than software.


You can say that as much as you want. Sounds completely reasonable, but good people are still going to feel like this guy. Good management should recognize this, and well, manage it, rather than have people grind themselves down, even if it is because of their own stupid pathology. I think it's just classed as being empathetic.


Sadly no. I've been depressed for over 20 years - this was the kick in the arse that I needed to spiral down into oblivion.


It's a job, not the fifth world wonder. That Corp is making money based on their market position, the software functioning is an afterthought. If it all breaks, the customer isn't going anywhere.

Don't fight management, leave.


No need for the condescension; I didn't imagine myself to be building some ivory citadel - I was working to ensure that changes required from a business perspective could be quickly and cleanly integrated without impacting the stability of the software.


The customers do eventually go. These companies will slowly fail, and they slowly fail because they specialized in customer retention (or more like trapping) either through legal (ie: lobbying, monopolizing, etc..) or illegal (dark shady patterns)


> The customers do eventually go. These companies will slowly fail, and they slowly fail because they specialized in customer retention

Maybe this is true in the general case, but there are so many exceptions to this that I feel it is not true enough.

Customers don't care about about using the best tool, they only care if it is good enough, and a computer/application/software that crashes once a day is actually good enough for most desktop workflows.

An OS that abuses the user might still be good enough that better alternatives cannot get a foothold. Same is true for web applications, enterprise systems, games, etc.

It's only when you get into the embedded space that you face the "quality or GTFO", because people have lower tolerance for malfunctioning appliances than they do for malfunctioning computer systems.


Your comment is why everyone should start their engineering experience as a consultant.

Primary thing that I learned being a consultant - you can leave and you don't have to suffer the disdain from the management. You learn to disconnect yourself and be replaceable.

It makes for a less frustrating life.

Sad that it happened to you. Don't invest yourself in someone else's child.


Sounds like you needed some workplace allies there.


"Most internal documentation only begins to make sense to a developer after they’ve developed an internal mental model of how it all hangs together. Most code documentation becomes useful after you have built the theory in your mind, not before. It operates as a mnemonic for what you already know, not as a tool for learning."

This reveals the secret goal of documentation: To build that model, not to document every last detail. The code can do every last detail, it's the model that is hard.

Set out with that goal and... yeah, I can't guarantee success for you either. It's a fundamentally challenging task. But at least you'll be off to a better start than if you think the primary purpose of documentation is to document what happens if you set this combination of flags. That has its place too, certainly, but if I can only pick one, I'd take the high-quality high-level overview over the stuff I can read the code for in 30 seconds.


Yeah, I've found the C4 model helpful for finding the appropriate level of abstraction for architecture documentation: https://c4model.com/

Code documentation, in contrast, should be auto-generated from the code.


Can you auto-generate the description of a function in a Python docstring from the code?

But yeah, totally into auto-generated (great example is dbt’s docs command: https://docs.getdbt.com/docs/collaborate/documentation)


The mental model really is not in the documentation, it is in the source-code modules how they interact with each other. Therefore I think OOP is a great way for building software. you need to create a mental imaginary world where the objects exist and interact. Then it makes sense.

But like you say it is challenging, even finding good names is hard. But basically, can you write a story about the software working, that would allow readers to understand it? Create user-stories but not (only) about the users but understanding that any module is a "user" of its components.


The thing is every project has mistakes. Things that aren't where they're supposed to be, that somebody means to tidy up sometime later, but just hasn't gotten around to yet. Every project has at least a little bit of a mess somewhere. When all you have to go off of is the code itself, then can be hard to tell the difference between the mess and the design.

A junior dev who comes in without much coaching, might just reference an anti-pattern from the "mess" section and replicate it throughout the code base. And then do that enough times, and a senior dev who gets brought in might conclude that there's no design at all, and that what it really needs is a rewrite.


Good point. And I'm not saying documentation is not needed. But that documentation should document the "theory" that already exists, or should exist in the code. When code is documented we do that in terms of the names of modules and classes and methods that exist in the implementation. But if those don't make much sense then neither does the documentation.

Maybe a good metaphor is to view the code as a simulation of something, and the documentation as the description of what that something is and how it behaves.

For instance say the software implements matrix multiplication. It is easy to document if its "units" correspond to the well-known concepts from the theory of linear algebra. But if the code implemented matrix multiplication but used random names for its modules classes and methods it would be difficult to explain what the code does.

Any explanation must assume that whoever reads it has a basic understanding of the basic concepts the software calculates and manipulates. But as said it is challenging to come up with such a theory and that must be done when the code is written, so the code itself reflects that "theory".


This is why I also didn't particularly enjoy answering questions concisely at my previous company. I still did, I just hated it.

Documentation can describe a system state, and how to use or approach it, but in my experience it really lacks in capturing the full depth of experience when it comes to interacting with it. All the little shortcuts and workarounds. All the debugging steps. Seeing something, and realising you've seen it before and solving it in 5 minutes instead of the entire day it took you last time. I could write a story about that day, but it wouldn't do anyone any good - they won't learn from that experience like I did and it won't spring to mind instantly. Assuming they even know where to find a piece written about their specific problem.

So when someone says "How do I X?" all I can think about is all the incidental things I've learned when trying to do something else. This builds the bigger picture. I can answer your question, but you'll just paste the code in and be back to ask more tomorrow. I valued the coworkers who treated such things as more of a discussion and learning opportunity than a transactional question-answer routine.


This is why effective documentation starts with run books.


I have a love-hate relationship with runbooks. I see them as tech debt for things you haven’t yet automated or made clear enough. If someone needs to go read a doc to understand what they need to do, you’re already behind.


I can't find it now but I remember reading a post on HN with the suggestion to make all your runbooks shell scripts, even if all they start out as a series of prompts walking the user through the checklist of manual tasks.

This way you can incrementally automate various pieces of it so that gradually the user is doing less and less, but there's continuity on their end: run the script and do whatever it says to do next.


I'm guessing this is "Do-nothing scripting: The key to gradual automation" https://news.ycombinator.com/item?id=29083367

Although the example uses Python, rather than shell.


That’s it, thank you!


I love this idea! The automate the easy bits (or the steps that are the biggest pain/time suck) until the whole thing is completed.

A tool like Jupyter Notebooks would be great for this - comments & code can be placed into a single document. I'm working on a project called unSkript (https://unskript.com) that is built on this idea.


> the full depth of experience when it comes to interacting with it.

This is the part that most people conveniently forget. Many people find it easier to create elaborate docs and processes than to regularly interact with the software system they've built.


> documenting the internals of a complex piece of software is a rare skill. A skill that most developers don’t possess.

I believe this is partially due to lack of training (technical writing rarely gets trained, and companies rarely invest in it as a skill), and sometimes probably also due to lack of exposure to high-quality documentation (which serve as role models you’d then want to live up to in your own documentation).

In addition, companies often do not reward expending time and effort on writing documentation, because it isn’t crucial in the short term. It’s similar to tech debt, just documentation debt.

While writing good documentation isn’t easy, the fact that it usually gets neglected is a cultural issue.


My take:

People "on the spectrum" are not great communicators, and also struggle to understand what it is other people know and don't know.

Also, documenting is genuinely hard, even if you don't consider that it changes all the time. Which it typically does.


I agree that not everyone has a knack for it. But I don’t think that’s the only factor. Software design/architecture is also hard and many devs aren‘t particularly good at it. We still recognize it as an important skill that requires education and training (and experience). If even just 20% or so of devs would get up to speed with how to write adequate documentation, and were enabled to invest the necessary time for it, that would already be a huge improvement.


Are you implying that a significant amount of coders are "on the spectrum"?

Not that I disagree -- working in highly technical fields this long, I could categorize 80% of my co-workers as lacking typical social and communication skills and you never know the real reason. It's to the point where I see women get promoted to management roles more often because they're superior communicators.


I am strongly implying that, yes!


You can do surprisingly well in this line of work by simply not being an asshole.


Yeah, the social skills threshold is amazingly low...


Everyone is on the spectrum. Coders are just closer to one side of it :)


I think that technical communication isn't the same as other communication, so I don't think it's a logical given that people "on the spectrum" would be bad at it. Technical communication is about conveying technical information, at various levels, with just a few constraints. It's a solved problem, really. It just needs to be followed to the letter.


Any examples of great documentation ? (For open source of course.)


I have no particular recent examples in mind, though I believe the Rust documentation is pretty good. Maybe browse these search results where similar questions have been asked previously: https://hn.algolia.com/?query=documentation%20examples


Ruthless end-to-end testing helps. Really hard on the short term, pays back on the long term. The suite is the specification.


That's a good way to prevent regressions but it's not the same thing as documentation or a mental model.

The tests tell you what it's supposed to do, not how it does it.


Or _why_


For a while now I've been dreaming about a system that lets me link tests to documentation. In a similar way that citations of other documents support claims in many domains, claims about software could be backed up by tests that demonstrate the claim. Then, when a test fails, the system could surface the relevant pieces of documentation (whether they're developer facing or user facing) so the developer knows the _why_ they're trying to preserve as they update some combination of the code, the test, and the documentation.


I'd guess you could get pretty far by just adding comments with links to product specs, JIRA tickets, or Slack/chat threads, as applicable.


That's what the commit message that added that test is for. And an example of why I'm strongly against squashing commits.


I agree. What about a situation wherein you have a QA team that stands entirely apart from the devs and they are the holders of the specification?


Automate the tests. Sure the QA group holds the final say, but if you have a test that breaks you don't have to ask them. Or at least you have something to base a.conversation on.

Note that requirements change, and bad tests will break on no requirements. Telling the difference is an exercise for the reader.


The tests are automated… by the QA team. Using a web-based tool for which none of the devs have access.


I see two ways forward, both probably not great advice.

1. Ask for forgiveness and do whatever you think is prudent regardless of org structure.

2. Find a better org structure elsewhere :)


I tend to agree. When I am capable of summoning the energy to care at this point, I make a run at #1. I have recently decided to actively pursue #2, as well.


Write your own automated tests that you control.


One of the most common tasks for QA teams is to write automated "outer layer" integration tests.


You guys have QA teams that know how to code?


I have multiple QA teams. Some are straight up regular users who cannot write hello world in any language. Others are programmers who got hired to write and maintain our QA end to end suite. A good end to end QA suite for a large project is complex enough that it needs everything any large software project needs: architects, tech leads, and all the other technical staff.


I've seen a recent multi-months training course for testers. Half of it is manual testing (culminating in a website-related project), the other half automated testing which includes learning some Python.


Really don't wish to go back to this. We don't have QA teams or QAs where I work anymore. We can get changes to prod much faster and our test suites are growing to be pretty high quality for the stuff our team owns.


Don't do that?


100% this.


Friction is the enemy of productivity. I guarantee that most employees simply decide not to mention ideas for projects that could help the company because of the headache. They will do the minimum needed to keep their jobs.


I know for a fact that this is true. Office Space was not a comedy - it was a documentary.


Observationally, C and related languages frequently use headers as a documentation and API specification point. The internals aren't revealed, but the expectations are distilled into one easier to reference location. I know I appreciate that more than machine (only) readable blobs that expect auto-doc tools to split out the salient information with the technical signatures. The human curation also allows for ordering that matters to organics who must integrate related data, rather than just alphanumeric enumeration.


>The internals aren't revealed

They are when devs put all the code into those header files.


...does that happen? Outside of C++ templates or inlining is there a need to pollute the header file?


A need? Definitely not. It's terrible practice. Does it happen? Absolutely, I've seen it many times. Why some C++ devs do this, I really don't know; I think it's just laziness.


> outline every anticipated step along the way, all the tiny minutiae that you foresee yourself encountering and how you'll deal with it

waterfall by any other name smells just as bad.

I think the reason is that senior management has no trust in the developers, which is the ultimate cause of the need to have waterfall. Each reporting level wants to show concrete evidence that those under them are "doing their best", rather than to have trust that they are.

Of course, it is understandable that people want concrete "evidence". But waterfall is the result, and you end up with big-bang designs, RFCs that are out of date because a change in circumstances necessitate a change that is not documented in an RFC.

It is a management problem, not a software development problem, imho.


Worse in my experience the quality of documentation (and tests) decreases the more a company is heading for insolvency for multiple overlapping reasons (at least for "startup| like companies).

This means if you want to buy a struggling or insolvent company it will most likely have bad documentation and tests.

But one of the most common steps when buying a struggling company is firing people (making the company fire people before buying it) and the selection of who goes and stays is rarely a good one. And it sets signals which make it mote likely for further important people to quit.


I think the reason to buy a struggling company is simply to get access to its IP (patents mainly) and customers, not to take over its operations. If it's struggling, it was already doing things badly and probably can't be saved.

Usually, when I see tech companies purchased, it's because the company wasn't struggling: it was doing quite well, but was small, so a much larger company bought it up in an acquisition to add its capabilities to their own, like the Borg. The big company gets IP, customers, revenue, and an already-working business, while the founders get a big payout.


Management is about process, people, and resources. If you ask a manager to solve a problem, the solution will often be some combination of:

- A defined and documented process

- Project planning or organization changes

- Staffing, purchasing, or contracting

These are fine tools for a lot of business problems, but they are rarely helpful, and often harmful, for software development.


I'm not a huge fan of writing a ton of documentation about the code. I am a huge fan of requiring developers to write in-line comments explaining what they're doing so the next person can build that internal model more easily. There should be some documentation about the system, but this is much more helpful if it only explains how to get the project running locally, including configuration settings and how to interact with it (if data has to be uploaded for a process, what should the data look like and how do you upload it). From there, a mid level developer should be able to locate the code entry points and follow the online comments to find what they need.

Just because it seemed obvious what you were doing and how things worked while you were writing the code doesn't mean it is, or that it will stay that way. Especially if that code ends up getting abstracted out. In line comments demystify code for the next guy way better than any amount of well written documentation.

As for what they're making you do with the RFC documents for changes, try writing your stuff as an ordered multi-tier list. The first tier should be the "manager" description of the change. The next level should be the more technical description of changes. The third tier is the location in the code where that change needs to be made (like a file path sort of thing, but you could use name spaces and even method names if you want). The forth and final tier if you need it would be cross references to other related items in the list and implementation notes/challenges specific to the file path. I've used this approach in the past myself. It's much faster, and it allows you to write a spec doc that isn't a huge waste of your time because it allows you to half write your code at the same time. It also provides a sort of semantic map from how the manager thinks about things to how you think about them, making it much easier for a manager to discuss it with you without having to write nearly as much.

Another benefit to this is you can often use stuff from the second and forth tiers to add in line code comments.


That does sound horrid. Makes green field projects look ever more so nice.


Sure, but your greenfield project today will just be someone else's brownfield project in a couple years


Do you work at Squarespace? This was exactly my experience there.


No.


Most companies either do too little documentation (they have a little page with the bare minimum high-level overview), or they do way too much (detailed change request forms for every change, which go into a file cabinet, and are never looked at again). Alas, it's really hard to get people to understand that documentation is good and necessary when they've only ever been exposed to one or both of those systems.


> The "solution" that we've implemented is to require a detailed RFC document whenever you want to create or modify anything.

I'd suggest just using the documentation. Manuals get used for doing testing and implementation. Using the documentation is like testing for it, and finding those problems right away is the best way I've found to ensuring that the documentation is correct and up to date.


Y'all ain't work on projects with NO docs and no OG devs. I'll take an outdated Google doc over nothing and day of the week.


"No" SWE ever got promoted for documenting someone else's code. Follow the incentives.


Huh?

Documenting a terrible project is an excellent way to propose and volunteer yourself into a new project of your own design and ultimately get promoted into lead/architect/SME types of roles. I don't know anyone who has done it any other way.


Yeah I've done this too.


> And in a Google doc, no less.

That whole process sucks and I’m sorry you have to go through it. It’s probably the best solution of the time. My one question is… Isn’t that why we have github issues?


Because the pointy-haired bosses in product and all of the various managerial minions don’t have GitHub accounts, so it’s either that or (shudder) a Confluence page.


I think we work at the same company.

Write your RFCs as markdown in a git repository. Stick it to the man!


My condolences to you and yours.


Bit rot is such a crappy metaphor.


In this context, I'm using "bit rot" as a metaphor in the same way that the author does:

> The first is that it’s a partial explanation for bitrot, the phenomenon where working software seems to deteriorate even when the code is untouched.


[flagged]


It's not 100% accurate, but what metaphor is?

I worked at an organization that had gone years without any updates: 10 year old dependencies that had never been updated, actively developed Python 2 code base in 2022, servers with 1000+ day uptimes and hadn't been updated since before the pandemic, on and on.

It made it difficult to get anything done because you had to wade through a dumpster fire to make the smallest change.

It certainly felt like bit rot to me.


Well, the author describes bitrot as:

> the phenomenon where working software seems to deteriorate even when the code is untouched

If the code is touched, and fails to keep up with dependencies, I might argue that's more a case of bit neglect. But maybe that's semantics.

I do agree that bitrot can be real though. Links rot off the web. If you're going to leave a project sitting on git without maintenance, you should probably capture the build context. Like shrink-wrapping a boat and storing it on land rather than just leaving it rusting away in the water for years.


It felt like “bit rot” to you because that’s how you defined “rot”, but it’s not how real rot works, which has nothing to do with changing.

It’s something that just breaks down without any changes in use case. If a wooden bridge rots away, nobody means that they were unable to add extra lanes. They mean it ceased to do what it previously did.

“Code calcification” is likely a better approximation of what you’re trying to convey.

“Bit rot” would be better fitting to actual storage loss, but this industry chose poorly.


It's supposed to be a joke, comparing the process of drift in the codebase with physical disintegration. Much like technical debt is not literally a balance owed to another party, or an object is not literally a physical lump of mass, and a class doesn't have a literal parent because it was never born.


Why? I'm not even saying you're wrong, necessarily...


I would call it developer rot. The code hasn't changed - and runs just as well (or badly) as the day it was written. It is the developers who somehow lose the ability (I don't know how - just read the code) to work with that code.


What do you suggest instead?


"Software subsidence"? "Digital subsidence"? The problem is that over time, the foundations upon which software is built decay, or need to be replaced...


I've worked with geologists and geological data and I had to look up "subsidence". I kinda had a feeling for what it meant, but it certainly didn't bring up any salient imagery nor help me understand the concept, which is kinda the point of a metaphor.


If you want some salient imagery, take a look at the first image on the Wikipedia page for "Subsidence":

https://en.wikipedia.org/wiki/Subsidence


Pretty sure it’s a metaphor. Edit: parent comment was edited.


A bad one


Why is it bad? What's a better one? What would a better one look like?


"context rot" is more aligned with what they are describing, though that's not a metaphor. I can see bitrot being a bad fit, as it's decay of the actual thing rather than the surrounding context.


Except that implies the context has rotted, when in fact the context is fresher than the system within it. While the context may have degraded in some way, the reality is that it's changed according to forces that have acted on it since the code within it was written and deployed. What's rotted is the ability of the system to meaningfully and correctly interact with the context.


I specialise in joining teams with problems (inability to ship, reliability issues, performance issues, etc.)

At least thrice I joined teams where all original developers and the manager was long gone. The situation for some reason looked very similar in all cases. The team is complaining about supposedly bad design that is preventing them from getting work done. But the system is also large and complex and they are unable to fix/rewrite it.

Lo and behold, in two out of three cases I found that the original developers actually did pretty good job designing the system but in all cases any one of new developers understands only small part of the design and is unable to contribute changes across the entire system, there is a core of the system that nobody understands even though everybody uses and the team has made changes that are against original ideas of the system quickly creating more problems and exploding complexity.

In all cases developers are only able to comfortably do some kinds of changes to the system that are routinely done (like adding new fields to forms, messages, etc.) that do not change how the system functions. Changing the basic structure of the system is a taboo.

In essence, developers treat "legacy" code as if it was some kind of framework or language runtime -- to be used but never to be studied to have its internals understood. (I will never understand this approach to development)

Making "non-standard" changes (yes, one team used this exact term!) pretty much always ends up with something resembling long archeological expedition with ancient traps, diseases and wild animals.


> In essence, developers treat "legacy" code as if it was some kind of framework or language runtime -- to be used but never to be studied to have its internals understood. (I will never understand this approach to development)

I was baffled by this as well for 15+ years until just last year I had a key insight: most developers don’t like to read. In fact, most people don’t like to read. Most people are intrinsically lazy and since growing your skills involves hard work, they don’t do it unless pushed to do so, either by life circumstance or necessity.

Time and time again people have asked me: “how do I get really good at $tech or software engineering?” I recommend a few books or send them my standard list of must-reads. In 999/1000 cases the person approaching me gives me that defeated look that I know means: “Oh. I was hoping you’d say something not involving working hard.” Most people are polite enough not to say it to my face.

When folks have problems with HTTP I ask them if they’ve read RFC 2616, and if not, I offer to bring them a nicely printed and bound copy. It typically goes unread though some use it as a reference. Only once did someone follow my recommendation and read it cover to cover.

Folks seems to lack a kind of basic economic perspective. Spend a week, month, something along those lines growing your skills (or even just 30 minutes reading the docs on that thing you just spent 2 hours declaring idiotic). Yes, this means probably giving up your favorite Netflix binge, video game, or drinking on weeknights in favor of study. But once these skills are internalized they pay back for a lifetime with good returns. Yet for some strange reason people prefer to keep thinking short term and so they never learn what they’re doing. It used to make me sad but I’m making peace with it.


> I was baffled by this as well for 15+ years until just last year I had a key insight: most developers don’t like to read. In fact, most people don’t like to read. Most people are intrinsically lazy and since growing your skills involves hard work, they don’t do it unless pushed to do so, either by life circumstance or necessity.

I knew a developer who said of such people “they spent six months in the lab to avoid two weeks in the library.”


There are some interesting things here. I may agree that most people intrinsically lazy but I don't think this is what is going on here.

I think at least to some degree people sort themselves into projects. Typically, the better ones that are also happy and capable with reading other people's code command ability to place themselves into projects that seem like more intellectually rewarding -- which means they are much more likely to form the original team for a new project than to join a project that is already legacy and is not meant to be rewritten.

What strikes me is that it actually is easier to write new code than to properly maintain/refactor old, foreign code. Working with large amount of old code requires a lot of hard, real planning and decisionmaking and learning to live with and adjust to decisions made by others in the past.

This hits "maintenance teams" twice -- not only they face actually more difficult task but they are also less likely to get good devs to help. It does not help that management is usually less likely to give resources to teams in maintenance mode than to teams that are developing new toys.


> What strikes me is that it actually is easier to write new code than to properly maintain/refactor old, foreign code. Working with large amount of old code requires a lot of hard, real planning and decisionmaking and learning to live with and adjust to decisions made by others in the past.

Right on the money. Everyone loves greenfield because you get to build things up from scratch, try out your own ideas, and there's this feeling of tremendous velocity. You feel like you're just tearing through code, kicking butt, delivering wins. Then the difficult requests start to come in, which usually means feedback from real human users. That's when the rubber hits the road and the grumbling begins.

And like you said, once the project is seen as maintenance it is 'not sexy' despite the fact that all successful software definitionally makes the most money while in the so-called maintenance stage.


I see where you’re coming from and this was definitely my attitude in my twenties: do the hard work to understand the underlying concepts and not just become a code monkey.

But I must admit as I get older, I don’t have as much time or patience to devote to this and I’m getting to terms with getting good enough to make a living rather than really understand $new_technology. I think this is partly from getting old and not wanting to sink so much of my own time and mental energy on computer stuff, but also from realizing how little it matters to most PHBs/middle managers who basically hold your fate in their hands. I’ve become much more cynical after a decade in the industry and I’ve realized how much of my own energy and health I have wasted in trying to get a deeper understanding of programming concepts. It was personally satisfying for a while, but it doesn’t pay off for most people. Most orgs want it done fast and cheap, they don’t want squeaky wheels, PHBs think in quarters and only want the thing to not blow up until after they get promoted in a year or two.

Developers who deliver that kind of low cost code fast (albeit low quality) have much more stable careers, better promotions, and get bonuses.

The rest of us ruin our mental health, paint targets on our backs, and don’t get as far. But man do we know our shit.


What you say is sadly true, our industry is overrun with bullshit artists and hustlers who are really only looking out for number one and the short term. I find it demoralizing at times as well.

What I've found is that good companies and outfits do exist out there, but usually they can't pay as well. Or they are boutique consultancies where everybody really cares about the craft...but then you have the realities of consulting to deal with (i.e., dealing with really difficult people).

I am not sure what to say other than: please don't give up hope. Things can get better but you may have to change your expectations or value system to find a place that works for you. Or if you have the stomach for it, try to build a product on your own leveraging your expertise.

For myself, a difficult but necessary change has been not wrapping so much of my self-identity up in 'being a great programmer.' Yes, I know some things in tech, and that's cool, but there is more to life than technology. But just to re-emphasize: I hear you, and it's tough. Wish you the best.


Thank you.

I agree it’s sad but I also have to look out for myself. There is no point in exhausting your energy trying to fix something where no one wants it fixed at best or is actively fighting you to fix it. It’s not even your money that’s being set on fire then, but it is your sanity.

Curious if you’ve found either a better company, or created your own product? It’s difficult to come to terms with mediocrity and needless toil, I went into this industry because I like well designed and efficient systems.


I kinda specialize at getting into legacy code bases, understand how they work, and quickly be able to make changes and clean things up.

But I don't think I've read any books on that. What I do is read the code!

I think can do this mostly because I'm interested in it. SW projects die because the code isn't maintained properly and becomes unworkable. So I work on being the counterforce to that, keeping the project alive.

Most engineers are into writing new shiny code, and hate "cleaning up other's mistakes". That's also often rewarded. The results are well known :)


Yep, that is definitely a skill. And you are doing exactly what I recommend: slow down and take the time to read the thing and understand it. Then go forward from there. Your interest also shows that you are intrinsically motivated, which many people are not.

You’re right that there are very few books available showing people how to do this. Usually “Working Effectively with Legacy Code” is recommended but it’s just one book and so can’t cover everything. It’s an area where on the job training and experience definitely makes a difference.


Reminds me of the story of the high school graduate who noticed that all of his peers were “following their passion” by pursuing various undergraduate degrees in underwater basket weaving, etc…

Rather than follow suit, he went in the opposite direction and did what no one else wanted to do… he started a septic tank cleaning company. He said that it was hard work, but lucrative… and that after a while, he woke up one morning and realized that he was passionate about other people’s shit.


Yeah, I try to avoid the cool, sexy areas. I worked with a few people with post Electronic Arts PTSD who confirmed it can get.

AI and crypto are very cool right now. They'll change the world and make some people billions.

But I bet you'll on average have a better career working on sewage plant management software :)


I knew a guy in real life who's dad built a profitable septic tank company from scratch. he expected his son to follow in his footsteps and take it over one day. The son passed; he could just not see himself in that industry and went into marketing. Caused a bit of stress in their relationship.


I can imagine how that conversation went. Something along the lines of “I’m sorry, dad. I respect what you’ve built, but I just don’t want to deal with this shit.”


… “I’d rather make up my own shit in a marketing career.”


> When folks have problems with HTTP I ask them if they’ve read RFC 2616

Well, that sounds like an utter waste of time. I just wanted to know if this endpoint responded to a GET or to a POST request.


Have you yourself read the RFC?

EDIT: to clarify, when I say “problems with HTTP” I mean actually understanding the protocol. Many people for example are unaware of the power of the Cache-Control header and all the things it can do. I used to ask people in interviews what the Content-Type header is for and enough senior engineers didn’t know that I simply stopped asking not to make them feel bad. It’s truly shocking how many people will go decades operating on muscle memory, never bothering to understand what’s actually happening when their code runs.


Do you ever ask about CORS? It always seems to be a great source of confusion with even more experienced candidates.


No, never. If the role needed someone with specific expertise or if CORS was a “hot item” for day to day development, then sure. But I’ve found that I usually don’t need to ask very complex questions to figure out if someone has skills or not.


Not OP. I'm starting to think that basic/mid level depth understanding of CORS is one of those canary-like items to judge if someone has a good grasp of web/http technologies. The other one is text encoding. You'd be surprised how many people don't know the difference between unicode and say utf8. It's all "black magic" to them at the end of the day.


It absolutely is. Especially when it "doesn't work" (not configured correctly.) Can someone look at a browser log and figure out what's going on? It's not just a front end issue, either. I've seen backend engineers set up crazy CORS configurations for internal APIs that would've been better served with a proxy off of a single origin. I even ran into an "architect level" guy that had no understanding of how that would even work. "You can POST without CORS???" seriously...


Sounds like confirmation bias. I know CORS and I know the difference between utf8 and unicode and I'm smart. Therefore anyone who doesn't is a dumb dumb.


Most people that haven’t run into encoding issues yet have no need to know the difference.

Thankfully basically everything is utf8 these days.


What's your solution for getting nicely printed and bound copies of things like that? Heck, how nicely bound are we talking? And how much does it cost?

(I recently looked into getting a copy of a certain specification printed/bound, but found that the cost would be a lot higher than I cared to pay)


There’s a service called printme1 that’s great, I’ve used it many times.

Or, if you’re into arts and crafts, you can get good home binding machines that are not very expensive. It’s actually pretty fun IMHO to punch and bind the paper but YMMV. :)


At the risk of being another intrinsically lazy developer who's not going to follow through, what is your standard list of must-reads?


I guess whatever helps you better understand work you are doing?

My reading list at any point is tied to whatever I am doing in my private or professional life. If my boss asks me to help grow the company my reading list will contain a bunch of stuff about company growth. If I have money to invest but no knowledge of investing -- you will see me listening to investing books while cooking, taking walks, commuting or long distance driving.

Basically, whenever I face a problem I look around for literature to help me with it.

I really hope to have an original problem in my life. Until then I assume that whatever problem I have there is somebody who wrote a solution to it and if I can't find it it is just because I wasn't searching hard enough.


Many more beyond this but these are my for sures.

People / Soft Skills:

* How to win friends and Influence People - Dale Carnegie

* Secrets of Consulting - Gerald Weinberg

* Peopleware - Tom DeMarco & Timothy Lister

* Nurtured by Love - Shinici Suzuki

* Turn the Ship Around! - David Marquet

* Never Split the Difference - Chris Voss

http://dhemery.com/articles/resistance_as_a_resource/

http://dhemery.com/articles/managing_yourself_through_change...

Macro Skills:

* Toyota Production System - Taiichii Ohno

* Workplace Management - Taiichii Ohno

* Thinking in Systems - Donella Meadows

* Fifth Discipline - Peter Senge

Agile:

* Extreme Programming, Explained (2nd ed.) - Kent Beck (the annotated bibliography is a goldmine)

* Chaos: Making a New Science - James Gleick

Programming:

* Implementation Patterns - Kent Beck

* Test-Driven Development, By Example - Kent Beck

* Refactoring (both editions) - Martin Fowler

* Refactoring to Patterns - Joshua Kerievsky

* Practical Object Oriented Design - Sandi Metz

* Functional Programming in Scala - Chiusano & Bjarnason

* Growing Object-Oriented Software, Guided By Tests - Freeman & Pryce ("The Goose Book")

* Modern Java in Action - Raoul-Gabriel Urma

* Java Concurrency in Practice - Brian Goetz

* Grokking Algorithms - Aditya Y. Bhargava

Architecture:

* Righting Software - Juval Lowy

* Release It! - Michael Nygard

* Site Reliability Engineering - Beyer, et al. ("The SRE Book”)

* Domain Driven Design - Eric Evans

* Introduction to Permaculture - Bill Mollison and Mia Slay

* Fun with a Pencil - Andrew Loomis

Design:

* All books by Edward Tufte, especially “The visual display of quantitative information”

* The Elements of Typographic Style - Robert Bringhurst

* Understanding Comics - Scott McCloud

* Design of Everyday Things - Don Norman

* Notes on the Synthesis of Form - Christopher Alexander

* The Timeless Way of Building - Christopher Alexander


Thank you for putting people skills up there first on that list! It was a small revelation to me when I at some point realized that people skills is just another thing I can just learn how to do. That it’s not necessarily something that comes naturally and then you either have it or don’t.

Also, the realization that people skills are actually no less important than tech skills in a tech setting.


> the realization that people skills are actually no less important than tech skills in a tech setting.

Yes, and this is hard to accept: they are more important than technical skills. I have worked with many truly brilliant engineers who didn't see their ideas implemented because they didn't have good social/conversation skills. The most common version of this is the engineer who gets miffed/irritated/pissed off if people don't accept their ideas after 5 minutes of explanation. Meanwhile, the hustler whose code totally sucks gets the win because they know how to schmooze the business folks (or literally just tell the best lie).

Hard technical skills are not enough for most people to be successful. There are the outliers with "super programmer skills" (and here I'm thinking Linus Torvalds / John Carmack level status) who are just so indisputably expert that they should be heard. But even then they may not get the win. You have to know how to talk to others.


It’s worth pointing out that John Carmack resigned from Meta because, among other reasons, he felt he wasn’t heard enough on issues he was trying to flag as dumb ideas.


I get why many people dislike the idea of working on those skills. The way you put it, some people might go like “I’m not playing ‘games’ like that, and I’m proud of it!”

So, the way I think about it instead is that I’m just another type of system that can be maintained, improved, evolved. And my communication with others is simply an interface. And, well, any engineer can grasp the idea that easy to use and well thought out interfaces are valuable and worth working on.


Also, you should study up on TCP/IP networking. You should be able to telnet to an HTTP server and write out a correct request by hand and have it work.


Oh you tease, TCP/IP is more than just \r\n and HTTP/1.1! We need at least 21 libraries for that!


Haha yes, for sure. I mean that it’s good to understand that HTTP is built on top of other things.

I can’t tell you how valuable it’s been at times to understand how packets flow over a network. When ECONNREFUSED first rears its ugly head many developers tremble. Over time you learn it’s just a slog of debugging. Emotional control while programming is invaluable.


Connecting to FTP server with telnet left as exercise for the reader... :)


So cool to see Bill Mollison in there. I live on a farm and work remotely in part because of that book.


Thanks! There is a lot the software world could learn from permaculture. I think software in many ways is more akin to gardening than building physical buildings.


I love you


That’s kind, thank you.


I don’t love you, but I do like you.


“I have just met you…and I love you.” ;)


i don't mind you. you're solid.


Not OP, but anything related to the kind of stuff you're working on. I'm doing WebAuthn stuff right now and I am reading through the spec before/to help falling asleep.

Specs are extremely terse and dry, and I never liked reading them. I pushed myself to read a few and now I find myself craving that kind of technical documentation in my work. The WebAuthn spec is pretty interesting and also has some even more interesting drama on GitHub issues.


I'm in the same boat as you. I'll repost this comment from when I asked another user here about easier ways of learning DDD (the Eric Evans book is pretty dense).

"I think a good place to start is through the service design lens — “This is Service Design Thinking/Doing,” Jon Kolko’s books, and IDEO’s handbook (all available on Amazon). These are all practical, business-oriented works, and will give you the language and tools you need to interact with service designers or conduct your own explorations.

In the tech side, I still think there’s a lot of value in reading through Booch and friends, even if you don’t go on to use UML in a formal way, and even old, deprecated approaches to modeling (think Shlaer-Mellor) can be valuable as an introduction to more modern (and generally more complicated) approaches to domain modeling.

For more academic and less practical works, look into philosophers of language and communication (Rorty, Habermas, Latour, etc) — if you don’t have a background there, try the “Very Short Introduction” series, which gives a good grounding before moving into further secondary or primary literature. What you get from these writers is a way to think about language, communications, and complex systems, so you’re building a conceptual toolkit. (Analytic philosophy, which is another, “mainstream” branch of philosophy, also has applications in the formal comp-sci route.)

Sociology and STS (Science and Technology Studies) kind of occupies a practical middle-ground between philosophy and design; I’ve often said that when we do service design, we’re really just doing folk sociology. There’s no shortage of textbooks, but I’d recommend looking into academic field guides for ethnographic studies (a fancy term for “going out and talking to people about what they do”) and ethnomethodological studies (a fancy term for “going out and talking to people about what they believe”). While the service design books will give you practical tools for conducting workshops and research programs, sociology books will give you a firm grounding on why those tools are used, and how to theorize effectively on what you uncover. I also like measurement theory, which is a branch of psychology concerned with understanding how to define measures and metrics — great tools for clearly defining data and reporting.

Finally, in addition to all this, consider digging into a corporate finance text or two; the three legs of the stool are product and service design; technical and operational architecture; and finance and sales. If you can read your company’s balance sheet and cash flow statements, you’ll be in a much better position to understand where you need to target investments, what the likely return on investment will be, and how much cash (or debt) is available to make things happen. Start building up a good knowledge base in all those areas, and you’ll have the tools necessary to know the “where, how, and why” to apply the “what” of technology to your organization’s problems. "


> Folks seems to lack a kind of basic economic perspective.

I agree with most of what you said, but this seems a bit ironic.

Your suggestions almost exclusively involve large investments of time with little established proof that they are efficient. Do you genuinely believe reading RFC 2616 "cover to cover" is an efficient way of solving the specific problems they came across?

I would wager most developers wishing to be "really good" actually have a concrete desire like a greater paycheque or employer in mind. If that is true, I doubt reading someone's booklist necessarily is their fastest pathway, and their economic perspective is exactly what stops them doing so.


A person that spends considerable portion of their time really learning new things will initially be slower at their work than people who only do work.

But over time this person will be getting better and better and better and at some point they will be able to do their job on the fraction of their time while still keeping momentum and learning more.

This has been my experience.

I have been spending 3/4 of my working hours learning new things for the past about 17 years after I realised this. The actual work takes a very tiny part of my day.

Software development really is a knowledge sport. Writing code is actually pretty small part of the task -- knowing what to write is the important part. If you are able to "write down the answer" so to speak, without spending much time getting there, you can be 10 or more times productive than everybody else, easily.


Um. In what I wrote I said a week or a month. That is not a large amount of time.

I think you missed the spirit of my writeup.


Or, if it's directly related to the problem at hand, do it during job hours.

Especially since reading is great, but actively engaging with what you have just rea, d by trying to solve some related small scale problem, is even better !


Can we see the standard list of must reads? I'm always looking for something new.


I've compiled a non-standard list, if that helps,

https://news.ycombinator.com/item?id=30651273

They're not about any technology per se, but mostly about exercises in how to tackle complex systems.


I posted it in a reply to a different comment on the thread.


Best comment!


> as much as possible, do not allow custom patterns/structures

This is key. Most engineers want to build frameworks instead of applications. But leave the frameworks to the framework builders unless you were hired to build a framework.

I can jump into a 10 year old rails code base and be productive right away if they stuck to the framework defaults. But invariably someone read some blog posts about how "rails doesn't scale" and built some rats nest of service objects/decorators/portsAndAdapters wtfs and it takes some serious code spelunking to figure out what's going on (hint - the end result is always creating or updating a database record, or making a single api call).

I would argue microservices also encourage bitrot. You can leave some service running on some ancient libraries for years it doesn't need changes. But if you have a monolith where you constantly keep the dependencies up to date - everything stays up to date.


I am sorry I have quickly deleted that part with advices while you must have been responding to it.

But this in my experience is truly important -- from the very start plan how a new member of the team is going to get really proficient at the system. Ideally, they should be able to immediately recognise/reuse patterns/idioms they already know.

People bitch and moan about boilerplate of Java applications. But when I join the project and I see controllers, models, repositories, entities, services, etc. I am pretty much at home as I know what all those things are doing and how they are connected to each other.

Whenever developers decide to run with their intellectual desires it ends badly.

I try to explain to people that typical business backends applications do not have custom problems. Most of those REST services are just supposed to receive query, run a piece of business logic, translate it into database call and then map response into specified format.


Maybe we work on wildly different things, but I feel like this is looking at things from too low a level. That is, I think uncommon or unfamiliar patterns are much less of an issue than no one knowing the whole critical path of a system or undocumented invariants, especially between systems. Eg maybe you must restart certain things in a certain order after making Config changes. Maybe there are times when restarts are/aren’t safe. Maybe you need to have a certain OS config parameter set to get good performance and new boxes won’t have it set automatically. Maybe there is an accidental circular or nearly-circular dependency between two systems and you’ll have a terrible time if you accidentally create downtime for both at the same time. Maybe you have a binary that’s been lying around and running as some corn job but no one has compiled/deployed it since 2015 and you don’t have the source code or really know what it does.

Mostly I’m thinking of more generic services rather than pure ‘business logic’ systems. These are the sorts of problems that Twitter might have in the future. Some of these are problems that Facebook might have gotten to discover in their last big outage.


I noticed that when people do not understand the system, things start to deteriorate until they can't do the simplest thing correctly or doing it takes way more time than stakeholders can accept. There is then pressure to get done faster, people start compromising on quality, etc. I hope you can see how there are many ways for things to start spiraling down.

Many probably noticed that very old, relatively simple machines, cars, tractors, printing presses, etc. can be maintained almost indefinitely. Many businesses do prefer old machines even when there are superior new alternatives and that is because the new versions are just too complex.

To keep maintaining something indefinitely you need to understand the machine enough to know every single piece that needs to be maintained and how to do it properly. Everywhere you need to lube it or clean it or to look from time to time.

Make something complex enough and nobody will have this knowledge. Things start deteriorating. Maybe the data in the database will start accumulating defects, maybe those defects start breaking processes, maybe the processes will not be fixed properly but the errors just get ignored possibly causing other data inconsistencies, and so on.

When you have people who wrote it and understand it fully they can very likely maintain it properly because they understand how to work with it, where to look, how to address problems. Loose them and if the system is complex enough the new crew may not be able to acquire this ability. And then it is just the question of how fast the system is going to be deteriorating.


> But if you have a monolith where you constantly keep the dependencies up to date - everything stays up to date.

At the expense of dependencies constantly breaking you, which itself contributes to bit rot by pissing off developers who find workarounds to pin their dependencies and/or switch to work on different products.


This is not my experience, but we update our dependencies multiple times per month. Of course if you let them go for six months or a year you'll be in the situation you are talking about.


I joined a big tech co and dove in to a huge unwieldy code base that had gone through the process you described above. I did a lot of reading of the code, and soon became the only one that understood it and could make big architectural changes.

But.. that is a dead-end job. There is no career path being the maintainer of a large legacy code-base. It was pretty good if you wanted to rest-and-vest, I could do whatever I wanted. But there were no great features, no demo's, no selling of the work. Even small changes were painful.

Moved to a different team where everything is new and building from scratch and suddenly opportunities open up.


As an anecdote to how developers treat "legacy" code:

As a fresh developer out of college I had the mindset that frameworks were something you use and they always work and all you need is the documentation. My first job had a lot of "core" code written by another team in another office we would use with exactly 0 documentation. I was trying to get our UI to do something specific but couldn't figure out how to do it by just looking at the functions available, so I ask my manager and he immediately knows what to do, makes 2 small changes (in my defense it was pretty hacky how it was set up imo) and I get what I want.

I remember being moderately pissed because I was already feeling the heat of asking my manager too many simple questions and I just apparently asked another one, so I say something along the lines of "How the hell would I ever have known how to do that, there are no docs available to say that is possible and that is not obvious at all."

He just looks at me and says "You read the core code" and I remember having my mind blown at missing something so obvious for so long. After that I voraciously read almost all "framework" code I could get my hands on, I asked more intelligent questions and my relationship improved my manager and eventually came to be considered a generally good developer.

Once I had this breakthrough I was seeing it in younger developers all the time, and now any time someone asks for general advice on becoming a better developer one of the things I say is "read a lot of code", and more specifically "read the code in your frameworks"


Late to the party but a potentially leading question if you ever see this:

- Was the original team slowly replaced due to cost cutting measures and thusly the people who joined aren't compensated well enough to dive super deep into the system to understand it?

At some point people need to be compensated to care is my theory. Engineers who inherit large systems are either scared or simply don't care, possibly a mixture. But compensate them enough in both salary, time, freedom to understand the code which is clearly critical in maintaining the long term viability of the system.

Thoughts?


mostly agree.

If I feel underpaid, I'll do the strict minimum to not get fired and spend my energy looking for another job.


So here is one thing I differ with you on.

If I feel underpaid, I will do my normal work as best as I can and start looking for another job.

I always try to leave on best terms. You really don't risk anything, you actually improve your possibility of fixing the problem without leaving. And in my case it led to at least couple more opportunities.

Not to mention the world seems small enough and on many occasions I joined the company only to learn I will be working in vicinity of somebody I worked with in the past.


> Making "non-standard" changes [...] ressembling an long archeological expedition...

This. This is how I felt trying to understand legacy core code. I kind of like that though. The idea of being able to improve/rewrite a decrepit piece of code excite me. But you won't be productive, and getting a (somewhat) complete and precise understanding of what it does and doesn't, take a lot of extra time.


Similarly I’ve seen sales and business teams start using/selling the product in a way it wasn’t intended, and then difficulties arise when the product can’t deliver what it’s been sold to do.

My currently company only did a specific niche in digital marketing but for sales goals needed to sell outside of that niche. Unsurprisingly, the product didn’t work for those use cases.


> What keeps the software alive are the programmers who have an accurate mental model (theory) of how it is built and works. That mental model can only be learned by having worked on the project while it grew or by working alongside somebody who did, who can help you absorb the theory. Replace enough of the programmers, and their mental models become disconnected from the reality of the code, and the code dies. That dead code can only be replaced by new code that has been ‘grown’ by the current programmers.

and

> Team stability is vital for software development. Each team needs to be composed of a majority of first-generation developers.

How does this interact with individual or career growth? I don't want to work for the manager who insists I stay on the first few projects I worked on at the company forever...

To take this seriously, internal churn (even if just someone being promoted into management, or specializing on expertise in a small part of the original project, or switching projects when they get bored) is almost as costly as external churn. Five, ten years later how much is their domain knowledge still that relevant to the people working on the code day to day today? It could be harmful if they've been out of the loop and make outdated suggestions, even!

Assuming and desiring your employees will stay in the exact same role indefinitely seems like a huge cause of churn.


I worked on a project that was paying the bills while another team was getting to work with new cool stuff.

What I learned from that project is that being indispensable sucks. That lesson has recurred in my career either for me, or when I got wiser, for other people.

It's not enough to write reasonable code that 'works' or document it as it is now, there's a whole unmeasured and thus under-encouraged aspect around maintaining a legible edit history. I often am trying to get into the head of the bug author to figure out why they thought this was a feature in order to preserve functionality while fixing bugs. They aren't always around, and they aren't always fun to talk to. If you have the history, the person is free to work on other things. To gift them to people they mentor, or otherwise re-home them. If you don't have that, if it's all in their head, they have to leave to get away from the project.

If I can figure out what you're doing I can figure out how to change one or two conditional blocks to fix a problem. Your code stays intact. If there's no history anyway, and the code is sketchy, I'm far more likely to take the code away from you by rewriting it. We can't have black boxes on the team. That's a ball-hog, and ball-hogs get benched.

If you don't show your work, then you're going to find you have fewer and fewer interesting responsibilities. Because "how we got here" is also a "why" and we ask Why all the time.


I agree, but am often outnumbered by people who enable "squash commits on merge" and that simultaneously add many process barriers against actually merging pull requests.


I want a meaningful commit history, that actually enables me to find the useful commit message. My coworkers often create PRs where the branch itself contains merges and a lot of bad commits that are not centered around a single piece of functionality or activity (like formatting, refactoring).

I try to have them clean it up but often the best thing I can get is a squash.


I defend atomic PRs and squashing merge commits.

It's simple, makes reviewing easier and works for 90% of the cases.

Maybe I'm missing something, but I find it painful to rebase into a neat history, and my colleagues would probably hate me to police them around to do it as well.


Everyone wants to be indispensable until they don’t. Getting people to plant two years ahead is an eternal struggle.


PRs should be small units of change. PRs should be the edit history. If your process involves one PR per feature this makes them large and unwieldy, hard to review, hard to test, and more likely hard to rollback.


I commend your attempts to do CI and PRs at the same time, but most places have too high PR friction to make that work.

So it becomes a fight between the two.


> How does this interact with individual or career growth? I don't want to work for the manager who insists I stay on the first few projects I worked on at the company forever...

Grow a garden, not a tree. Let's disambiguate the word "project" from the word "system" (not "product" -- that's sales). Let's call a project a time- and scope- limited effort to create or modify some system(s) in your suite (your garden). I think it's a common mistake to mix these two up. If projects just drag on forever, then yes, employees can feel stuck. By this definition, I certainly would not want to work on one project forever.

What about working on one system forever? The problem there is that to stay busy, you're forcing attention on a system that might not need attention. At the end of a project, a system should be fulfilling its purpose, and it should do so indefinitely, forever. That purpose may expire, but the system shouldn't. There should be no urgency to keep messing with a working system.

So let's work in one garden forever. Systems will grow; we'll prune and re-plant them; we'll give the healthy ones the barest maintenance it needs; we'll give the dying ones the sweet release of death; we'll shape and braid them together. All your institutional knowledge about how System A works will be great when you're writing System F that depends on System A, or when we're splitting System A into Systems A1 and A2. I would absolutely love to work at a company where I can work in one garden for the rest of my life. That's my dream job.

Sidebar: do not make the mistake of assuming "system" means "microservice"! That's only one of many ways to define system boundaries.


I agree with this - while at a single less-than-a-few-thousand-people-company I'd generally call that a single "garden" - and think it's a good extension on the original article. The author, though, focuses very narrowly on the "code" level instead of the "components of the system" level.

If you can grow people into being the ones who know how the components of the system work together at a layer above how the code for any given component works, you can have a retention plan and keep institutional knowledge. (Or even then move people into a layer above that, as the system grows, etc).

You still won't retain everyone, some people want to jump between gardens, but you will be able to retain a LOT of people, and it's much better than telling people they have to own all their individual lines of code forever.


> At the end of a project, a system should be fulfilling its purpose, and it should do so indefinitely, forever. That purpose may expire, but the system shouldn’t. There should be no urgency to keep messing with a working system.

Wonderfully stated! Losing sight of this is I think where projects start to run into trouble with scope-creep and the ”fix” vs “enhancement” issue. It also shifts the perspective of what is a satisfactory state for a finished project vis-a-vis maintenance plans, dependencies on aging systems, etc. Your garden metaphor is also beautiful and IME accurate.


I don’t wholesale agree with the writing but it does mention working with someone who worked on the project and can share the theory. In that case, a new dev is hired, and you instill all the knowledge of the system in the new dev. Once you’ve trained them enough, you can move on. New devs will adapt and create new theory and solutions. Rinse and repeat.


That kind of misses what is being said in this article. The first generation programmers support a constrained population of second generation developers, and over time the second generation developers have written enough code that they become the first generation.

A big component of what this article is saying is basically that knowledge transfer in the way you're describing doesn't work, and if you dig down to the theory this article is based on, new devs adapt and create their own theory and solutions was specifically called out as a problem. In case 1 of this paper, it's described as second generation programmers submitting patches to the first generation programmers that don't make use of the structure of the program, and add things that are trivially done by the existing systems. Then, a third, disconnected generation of programmers takes over the maintenance from the second generation, and they've added so much cruft to the system that the original powerful architecture can still be seen, but isn't in use because of all the additions.

[0] https://pages.cs.wisc.edu/~remzi/Naur.pdf


> A big component of what this article is saying is basically that knowledge transfer in the way you're describing doesn't work

Knowledge transfer doesn't work at all :) It's not a thing that's possible. The best we can do is for someone with knowledge to attempt to explain it, hope they do a good and complete job of it, and then hope that the explainee is able to internalise it and come to the same/similar conceptual understanding that the explainer had in their mind.

It doesn't tend to be done very well at corporations. It's a skill that good teachers have developed after much practice, which isn't something we tend to hire for.

And it requires favourable conditions, and one of those conditions is not "it's my last day tomorrow and the boss asked me to bring you up to speed on what I've been doing these last six months. You only had 30 minutes free in your calendar, so... let's go"


In the underlying theory it's described as actually worse than that. A fully documented system explained by the first generation developers wasn't enough to transfer knowledge, the documentation only made a difference once the programmers had built a working mental model of how the software worked, and then they still submitted patches that would duplicate functionality because they didn't understand the system.


But this doesn't boil down to "you have to replace the impossible problem of knowledge transfer with infinite employee retention"?

Is that an improvement?

(I'd also argue that I've worked on systems where I've developed a better mental model of the problem than the first-gen people I inherited it from, because I as a maintainer was under less pressure to get anything that worked out the door initially.)

EDIT: and looking at the paper you linked there, https://pages.cs.wisc.edu/~remzi/Naur.pdf , I'm in complete agreement with "the designer's job is not to pass along "the design" but to pass along "the theories" driving the design" - it was always easier as that maintainer to take over a project where people could tell my why not just what.


Yeah, I was going to comment something like this : on a complex project even "first-generation" developers start out something more like """third-generation""" : after all the goal is to solve some problem, and the clients themselves might not even actually know what it is !


> they still submitted patches that would duplicate functionality because they didn't understand the system.

A lot of the time they don’t want to understand the system. Maintaining some old legacy system is no fun. Programmers want to do new things their own way. And if there’s no one around to guide them then they will.

This is a management and cultural problem. Enterprise software resembles failed open source projects - no one wants to work on them so they die, get forked, or re-written and replaced.

Contrast this with successful open source projects. A vibrant project will integrate new developers into the culture (or show them the door), and conversely developers who want to change things will have to prove themselves.


The Naur paper seems to take as fact that even if motivated to learn, taught by the authors, and given good documentation… new developers just don’t pick up a complex system. The paper used a compiler for some language Y onto a target system X as an example.

Personally, I don’t our ability to learn is that bad. Given time to come up to speed and motivation to read the code and understand it, and some good (consistent) coaching from people who fully understand the code, I believe new developers can be integrated into a complex codebase that they haven’t written.

But this really draws a stark relief from the way software engineering on existing code is treated by every manager I’ve ever met, which is likened to reading a book once in a language you already know. One read through is enough to grok it. If we land somewhere closer to this source material on the spectrum I think that’s a win.

I also look at my own thoughts on existing code. I’ve had the strong urge to refactor out old code I didn’t like… and that is interesting to me. Did I not like the style or just not understand it and want to make my own mental model my way?

The idea that we’re just replacing engineers and they are just re-writing the same code with the same outcomes because we think of them as Lego blocks is interesting as well.


That's that "second gen" vs "first gen" thing but it actually leans in hard to the "no movement" right after introducing that concept - the "Each team needs to be composed of a majority of first-generation developers" quote is from that paragraph after the distinction.

If you try to fix the theory knowledge/documentation/practice problems purely through insisting the "first gen" stays where they are, they're going to leave you for more interesting work, and then you're in exactly the situation you wanted to avoid. The only way out is "more effective practice of theory and knowledge transfer" but all the author seems to have to say about that is "This is a team management issue that can only be addressed by a manager who understands the fundamental nature of software development. There is no magic development process that will prevent these problems. It takes skill."

E.g. that's the real hard part yet they completely punt on trying to dig into it.


> How does this interact with individual or career growth? I don't want to work for the manager who insists I stay on the first few projects I worked on at the company forever...

To me this is the a huge incentive for building strong teams. Nobody should be indispensable; it's a disservice both to the company and the person. Pair programming, collective code ownership, intentional cross-training, good automated tests, continuous deployment, and good automated monitoring have all been very helpful to me there. And vacations! Everybody should take long vacations where they are out of contact. By managerial force if necessary.


+1 on long vacations. My team is in Europe with 38 days of PTO and while it offends my American capitalistic sensibilities, it's created so much resilience because everyone is always on vacation, we've built our company ops to reflect this reality.


Like Netflix's chaos monkey but for people; unplug anyone from the system and the system should still work.


At least one CTO has actually tried exactly that: https://danlebrero.com/2021/06/30/cto-dairy-lucky-lotto-chao...


It doesn't "offend" "capitalistic sensibilities". It's just a result of optimizing the wrong metric.

Decision makers for American companies tend to use "Time spent at work" as a proxy for "Productivity". That used to work just fine when the job was pulling levers on an assembly line but turns out to not make sense when you are talking about software development.


I think the phrase "American capitalistic sensibilities" is well used here. American capitalism has a long history of optimizing for that particular wrong metric. It's culturally distinct from, say, Mittelstand capitalism: https://en.wikipedia.org/wiki/Mittelstand


Is having longer PTO in your business a detriment or neutral/net gain to overall productivity in your experience?


> My team is in Europe with 38 days of PTO and while it offends my American capitalistic sensibilities

Do you actually think of yourself as a capitalist though?


Kind of funny that being allowed to live life outside of work is offensive to American sensibilities.


He speaks for himself


Lead moves on to something else, everyone moves up a role, add a new junior. Repeat as often as necessary.

Alternatively: just promote and pay your people as they develop, even if they're in the "same role".


Because when you don't, your folks write reviews like this: https://www.glassdoor.com/Reviews/Employee-Review-Inspire-RV...


> How does this interact with individual or career growth? I don't want to work for the manager who insists I stay on the first few projects I worked on at the company forever...

The first project is maybe a bad example but if we say the "nth" project instead then:

- not always changing members doesn't mean never changing, companies should just not want you to jump between projects all the time (except maybe as junior programmer) and you shouldn't want this either as it's hard to build up proper deep expertise this way (instead of a lot of shallow expertise)

- if you are still in the same company and the company is healthy then it should be fine if you get asked questions about your previous project for some time after you switched (through not arbitrary, just as an "emergency" thing)

The problem is that the concept of carrier and seniority is seriously messed up in the software industry. Often shallow knowledge about a lot of things is more valued then actual expertise in the things needed. Similar you will find a surprisingly lot of people believing that a senior engineer which doesn't try to get into team lead/people managing positions is doing so because they "surly are incompetent and shouldn't be hired" (IMHO completely rediculus but I have still seen it often enough, just most times in a less directly phrased way). But in the end senior software development skills and team lead skills are distinct skill sets. Implicitly pressuring someone who is good at solving technical problems into a team lead position (or the other way around) is just a pretty stupid decision from a human resource utilization POV. (This depends a bit on the definition of team lead and yes team leads also need to have technical skills but most important they need to have the skill to listen to their team and not get stuck on their opinions, etc.).


I've worked in incident/crisis management for several big, complicated, grown-via-acquisition companies with a tangle of internal systems that were never quite fully integrated.

When TSHTF and we need some expertise from the original builders or operators of a system, it's a lot nicer to have them on another team than at another company. If they still work for us, somebody can make the case to them (or their boss) that borrowing them for a few hours to fix it is in everyone's interest. A lot of times they are in some kind of management position now and they kind of smile and say "Wow, I haven't thought about that system in a long time. Sure, I can take a look." and it's even kind of a fun diversion from whatever budget meeting they were in.

If they work for somebody else, the answer is often "sorry, I'm busy" or just a hangup when you explain who you are and why you are calling.


An employer shouldn't want that for you either. I think what this ends up being is an argument for good documentation and onboarding so you can transmit the "theory" to other people.

Reasonable amounts of churn are manageable if you do a good job of acculturating new people into the team. This has actually been one of my concerns about the switchover to WFH. I know a lot of that acculturation used to happen by osmosis and people working next to each other. I think my team doesn't do as good of a job maintaining it when we're all working separately. We're a lot more efficient now, but I think we haven't figured out a good way to share and transmit context like we used to and I worry what happens if we hit a period of flux in our company. I worry our team culture is a little more fragile now.


> I know a lot of that acculturation used to happen by osmosis and people working next to each other.

I used to think this too, but I think we need to be cautious of magical mechanisms for knowledge transference. I think the real mechanisms are code reviews, discussions of issues+code+project, consults / shared problem solving, design reviews. Just sitting next to someone doesn't work, there needs to be a shared task or problem for knowledge transfer to happen.

I think all of these shared tasks happen with remote workers just as effectively, as long as you have good team comm hygiene.


The biggest difference between remote and in-person is that many of those things can happen more easily without being scheduled. The organizational management skill bar you need to hit as a team is lower when the communication friction is much lower.

Talking to your teammate who sits nearby in person is both lower friction and higher bandwidth than sending them a chat method.

"Adhoc conversations" don't magically lead to knowledge transfer, the probability of any adhoc convo being long-term-meaningful is low, but they greatly increase the cumulative probability.


> How does this interact with individual or career growth? I don't want to work for the manager who insists I stay on the first few projects I worked on at the company forever...

By documenting your work and/or mentoring a junior employee to pass on your tribal knowledge.


"Many teams in the industry constantly rewrite parts of their code. Not because they keep figuring out better ways of approaching the problem but because nobody on the team has an accurate mental model for how it works and how the code fits in with the rest."

This part rings very true, as someone who's been through plenty of rewrites / "make module X not suck" projects. A side observation here is that usually the original author (sometimes long-departed or departing) understands very well the limitations/flaws of the original system/implementation, but can be excluded from the design of the replacement for any number of misguided reasons. Trying not to bruise the ego of an early employee, thinking that they wouldn't agree with any changes, whereas those are often the people in the best position to guide a rewrite, and often would love the chance to fix some of the decisions they had to make originally.


> A side observation here is that usually the original author (sometimes long-departed or departing) understands very well the limitations/flaws of the original system/implementation, but can be excluded from the design of the replacement for any number of misguided reasons.

I relate to this so much. I'd offer an open letter to some poor anonymous soul who inherits one of my dumpster fires. Because I'll certainly never be given the chance to revisit anything.

Yep, my shit's broken. It was written long ago, under different constraints, for a different audience. I made the best trade-offs I could. I documented them! Though you'll probably never find my writings, and if you do trip over them, you won't understand them yet. Today, I'd scrap most of it if given the opportunity. But to whomever is now taking on the rewrite, you know that little nugget at the core which perplexes you so? The one that doesn't fit your mental model of any type of programming you've touched in your career? That there is the core value proposition that makes it all possible, and if you throw that out, you've doomed yourself to learning my wisdom the hard way. If you're at all up to the task, then the next few years of your life and the remainder of your days at this company will be spent fixing the same problems by reading the same papers and obtaining the same obscure domain knowledge. No, it can't be abstracted away. Yes, it's fundamental. No, no one else will really understand it either when you try to explain it, because no one else without the accountability you now have will sink enough of their time into building the mental model you've had to construct. Good luck.


Why do we bother?


On a good day, I'd say we do it because it can be fun and rewarding. It's an escape from the regular daily grind; something beyond the drudgery of say React, CRUD, the frequent silliness of business logic requirements, or whatever the mundane might be at your own workplace. It can also earn us the respect of those peers whom we ourselves respect the most. A knowing smile and a nod between us is priceless. Maybe we each count ourselves lucky that at least we were spared the other's tribulations.

My own efforts don't quite earn me "the big bucks" that I read about at companies I'll actually never work for. Just a respectable east coast income that I shouldn't complain too much about. Don't know that I'd be happier anywhere else anyway. The bills get paid while I'm making the world a better place.

On a bad day, I'd say we do it because we're suckers for punishment. It's in our nature.


This is very true. On multiple occasions, after taking over ownership of code for which the original author wasn’t available anymore, I ended up rewriting it bit by bit, according to my progress in understanding it. In some ways, rewriting a piece of software is the best way to understand it deeply, and/or to uncover the gaps in one’s understanding.


> In some ways, rewriting a piece of software is the best way to understand it deeply, and/or to uncover the gaps in one’s understanding.

Fine, so long as your rewrite is not checked in. Otherwise, this approach will surely lead to chaos when prior developers who figured it out now have to re-learn your version, resulting in the exact problem this article is addressing.


I explicitly mentioned this is in situations where the original authors aren't around anymore, and hence you're on your own figuring out and maintaining the code.


It is the case for most code that the original author is gone. However, there are likely to be other developers around that have encountered the code or maintained it in the past.

Rewriting and submitting code mainly because one does not understand the original version is usually not a good idea; understanding the original code should typically be a prerequisite to replacing it with other code. Otherwise, how would the developer know that the new code was better?


I agree. I would add that sometimes the existing team only want to make incremental changes to their existing software, rather than make something new, and that can make team dynamics... complicated!


I’ve heard Google are quite rewrite heavy, as an intentional strategy. Not that they rewrite everything all the time, but that they’re quite open to rewriting significant sized systems, and do it quite a bit more than most tech companies.

Not sure how true that is, or if it’s more myth. Also not sure how common it is to have original devs participate in the re-write, or if this is more something they do if the original devs have moved on. If any Googlers on HN could chime in, I’d certainly find it interesting!


2 systems: One that you’re supposed to use, that isn’t finished; one that’s already deprecated.


I have seen half a dozen otherwise useful projects retired or criticized because "the original developers are all gone and no one understands it any more."

The code worked, and continued to work, and didn't need really active development, so the org decided the project's programmers should move on to something new, or that the knowledge they have isn't especially valuable, and the programmers aren't worth keeping happy.

And a couple of years later, no one knows how to update the code for a changing outside environment, updated input styles or whatever. And all that investment is gone.


But someone can figure it out. It doesn't matter that nobody knows anymore, if there's a real need with no alternative, someone can figure it out.

I used to work for a company that had an internal tool. It wasn't used anymore, everyone that worked on it was long gone, the source code was "lost".

There was some emergency and someone needed to use the tool to look at some old data. Lots of panic and people claiming it was impossible.

I opened up the executable in ollydbg, patched the executable so it worked properly, and life went on.

I'm sure the source code wasn't lost, it would have been on a tape backup that people were too lazy to try and recover.

If the source code is available then it's even significantly easier. I don't buy this whole "nobody knows how to update the code" reasoning.

If the code can't be updated, it's a matter of incentives and prioritization.


> But someone can figure it out

Actually, in most cases - no, they can't. Or, rather, they can't figure it out as fast as they're "needed" to.

> if there's a real need with no alternative

What happens instead is that somebody with no real knowledge of software development says, "we need this change made in two weeks. We need this." That this might be impossible for any human being, living or dead, is completely ignored. If the programmer this is dumped on even suggests making any clarifying improvements to the code, even that is rejected because "we need" this.

And two weeks come and go, something was changed because there was a deadline, but the something that was changed broke a dozen other things nobody even remembers were there, and now there are bugs waiting to be discovered by unsuspecting users.

> it's a matter of incentives and prioritization

I know what you mean - it is, technically possible but it's never feasible because it's not predictable.


>Actually, in most cases - no, they can't. Or, rather, they can't figure it out as fast as they're "needed" to.

I've forensically self-onboarded a few times and yeah, it's at least 12x more expensive than well written docs + pairing.

It's economic for some projects but it's still crazy to do it if it's at all avoidable.


When you run up against this wall, it is often easier to write new software than to maintain the legacy code. Long term you are duplicating a ton of work at huge expense, but that is frequently the fate of successful projects: to be replaced with something sub-optimal that is nonetheless more tractable because there is less of it at the beginning and rapid feature development makes it easy to demonstrate value.


More often I've seen that all that fast development time is spent trying to replicate features of the old system that were missed or deferred when designing the new system. Strangely, when they have achieved feature parity, the new system often doesn't seem so easy to work with.


It’s definitely easier to write new code, but faster? I doubt it.

I see a lot of the time programmers doing the easy/fun thing rather than the hard beneficial to the business thing.


Part of this is resume driven development.

Loyalty gets you very little in today's climate. Why should I spend time understanding the current system that was developed on yesterdays hotness?

I need to spend my time here developing on the latest trends on a new solution (learning more from running into the same walls the current system did) - not learning the domain knowledge + old framework, so I can move on after a year and earn more at the next place.

Is this good for the world? No. But unless you want to swing the hammock and work at institions that value incumbents, the incentive is to do whatever work improves your resume, not what benefits the company.

I don't personally like it, and I often see old systems that are just fine get thrown out and replaced with the a less featured replacement that grow into the same kludge as the first, but I can't ignore that when you do that you learn way more and have better examples to point at in interviews.


> Why should I spend time understanding the current system that was developed on yesterdays hotness?

Simple. Because that is your job: to solve problems for the company using the current technology that the company has the resources to handle.

Also, the newest hotness is not as hot as you probably think.


It never is. But incentives drive behaviour, and the incentives for someone's career in this market pull in that direction.


>but I can't ignore that when you do that you learn way more and have better examples to point at in interviews.

"I replaced an unmaintained, buggy legacy tool with a new version with X new features" >> "I maintained a legacy tool"


> I don't buy this whole "nobody knows how to update the code" reasoning

Me too. At best, they would need the previous guys only in one condition: very short time constraint (have to figure it out "today"). Otherwise, it's not hard to figure out at all, even codes from a complete idiot. If he can code the program that worked, the code is very likely be figured out by experienced people very soon.


> be figured out by experienced people

Sure, you can figure out how to change it to do some very specific thing that somebody identifies as needed. What you probably can't do (at least not in any reasonable amount of time) is figure out all the things you're going to break in making this change. If they followed good software development practices, left a good comprehensive set of unit tests and documentation then you could do that - but they didn't.

> even codes from a complete idiot

If I was wrong, there wouldn't be anything wrong with global variables or goto statements - any code that "works" would be isomorphic to any other code that "works".


> If they [...] left a good comprehensive set of unit tests and documentation then you could do that - but they didn't.

Then you can start by writing the tests. That forces you to dig until you actually understand what's going on.


This can be a lot of fun!

My "trick" is to write black box test without understanding the code. Like this:

1. Send in some data 2. Observe what data comes out. 3. Make a test asserting that! 4. Go back to 1.


> identifies as needed

That's how it works even with the same guys on projects. If you think it would break (no tests found), write the tests first. I don't believe someone would write a complete mess million line of codes that works without some tests and docs, that would make him kinda genius.

And global vars and goto is not hard to figure out, it's hairy for sure.


> I opened up the executable in ollydbg, patched the executable so it worked properly, and life went on.

That makes you a great engineer that saved the day. Not all companies have great engineers that can save the day, or keep them, or even identify them.

Sometimes you also need to add features, which can be quite a task if you don't have the source code.


100% agree. One of my friends, in her first software engineering role, was handed a binder from 1987 and told to update some things.

Other coworkers had interacted with the system a little, but not extensively. It was a bunch of C for (rock & ore) mining software. It was intimidating and it took time, but she cracked it, and then happily (& justifiably) bragged that she added features to code that had been written before she was born!


I'd be proud if I were the original author, too. My code lived long enough that someone who wasn't even born when I wrote it was able to add features to it.


> I don't buy this whole "nobody knows how to update the code" reasoning

As an anecdote, your example demonstrates the truth of the reasoning. Absent extraordinary or unorthodox effort, such as patching the executable manually, programs do suffer from loss of understanding. Yes, you made it work, but can you really claim to understand the program and how it was written?

Of course, given enough time and effort, most code can be reverse engineered to a level of understanding good enough to work on it. In practice, most organizations are going to decide it's better to spend time and money on a replacement.

> I'm sure the source code wasn't lost, it would have been on a tape backup that people were too lazy to try and recover.

That's certainly one, rather uncharitable, way to look at it. But what constitutes sufficient effort, given time and money constraints in the real world? Unless that backup literally contained the only copy of information essential to the continued existence of the company, there's a limit. And what if they did find the backup, but it was on a magnetic medium that had degraded to unreadability?

I've made my career working on legacy code. There are definitely ways to understand systems even when nobody who originally worked on them is around, but business constraints have always determined whether or not the effort proceeds or is abandoned.


I think most devs don't want to figure it out. Let's face it, working with legacy code is just not fun unless the code is well written (and even then a lot of devs still don't want to touch it because it's "old tech" and doesn't help their resume).


Flip that: most companies don't want to pay what it costs to get someone to do this kind of work. Most devs would do it if the incentives were good enough.


Maybe in some companies developers work very hard and are short on time. Maybe you are in one of these companies yourself.

In my own experience, devs aren't often overworked and do have the time to do stuff like this. They just rather not spend the time on it for various reasons.

What incentives would get you to work on an old legacy project?


Are there consultancies that specialize in this kind of thing? "Help us kick this legacy can down the road the bit, nobody here understands it and it's not worth hiring for." Asking because I enjoy this sort of work :)


It's probably not much of a thing because companies don't want to spend a lot of money on maintaining legacy code, and are only willing to throw a lot of money at a problem when it's a huge emergency, but by then it's too late and your consultancy wouldn't be able to get the job done in time no matter how good you are.


Yeah, every consultancy. The ones that look like don't do that kind of work still do, because they somehow have the magic ability to turn a greenfield project into legacy code in the space of about 2 months.


My very first commercial program was a Fortran 90 thing that could write its own source code out to the filesystem if asked. Updated itself as part of the build. I still quite like that as a feature.


... Why would that be useful? Don't you have the source code in front of your face as you are working on it?


> ... Why would that be useful? Don't you have the source code in front of your face as you are working on it?

Maybe not, actually. Assuming that the code was written in the 90s, there probably wasn't any version control (only backups at specific milestones).

With no version control, there's a 50:50 chance that the source code you found for some deployed version is not the same as the code that was backed up.


Replying to a post saying > the source code was "lost"

Sure, I had source that I had written. In source control even, was using fossil. But I thought my binary might end up somewhere decoupled from that source, with some other engineer tasked to modify it, and I hope they find the dump source option listed under -help useful.


> It doesn't matter that nobody knows anymore, if there's a real need with no alternative, someone can figure it out.

Well, by that logic, someone can build it from scratch.


> I opened up the executable in ollydbg, patched the executable so it worked properly, and life went on.

I've done simple binary patching, and thank my lucky stars that:

1. The replacement configuration value strings were shorter than the original

2. It was written in C, using nul-terminated C strings

If this was almost any other language, I would have more work even if the replacement string was shorter, because I'd have to fix a bunch of offsets everywhere.


what was the update? the kind of update that "programming as theory building" is talking about is like, the next version of a piece of software.


Yes, but the comment I replied to implied that software will just stop working. If software has been working for years and then stops working, it's usually something fairly small than can be hacked quickly.

In my specific case, the tool had a whole bunch of hardcoded values. It checked authorization against an LDAP server, that all changed. Connected to a sql sever that moved + credentials changed. Assumed certain files existed on certain network drives which were moved.

Technically, it could have been solved by faking all the infrastructure. It also could have been solved by digging out the source code from tape drives. But everyone was running around saying it was "impossible". I was shocked how quickly people tossed out "impossible".

It could have been done with a simple hex editor, but the new values were longer than the old values, so the strings didn't fit. I put the new strings at the end of the .data section and then just changed a bunch of offsets.

I agree that if you're writing the next version of the software, you can't do that quickly when nobody knows how the current version works. But chances are, you're not writing the next version of the software quickly even without churn.


it's not really about how the software works. the source code says what it's doing. the thing is the source code is the product of a theory; a theory determines how you respond to the world. if that theory is lost, then updating--in the long-term sense--becomes hard, because the theory that you form might (probably) be incompatible with the theory that made the software. this incompatibility might make producing functioning software difficult, but more likely, the mismatch will make choices that don't make sense to, say, users, appear to be the obvious thing to do.


Sometimes it's worse when they start tacking on changes in an inconsistent way. It's always painfully obvious when a company is shipping a product that has been acquired multiple times, and/or hacked on by contractors that don't care about the past or future of the project. I'm looking at you Aruba, Cisco, and pretty much every network vendor.


I've seen the first part of this story a lot.

Software product is delivering value, maintenance isn't needed much, people move on to other projects[0], people forget about it, then a couple of years later a change is needed.

But how would the first response in that "couple of years later" scenario be "throw away all that investment and start from scratch" instead of "dig into how it works"? That's not a long time, really.

[0] this is a good thing, IMO. If every project needs constant maintenance from its "owner" you as a company are going to rapidly run out of resources to do new things.

(There's a closely related thing, here, though, that as an individual or a low-to-medium level manager, keeping track of these risks and low-level maintenance areas is part of your job to find ways to keep it from ever turning into a disaster. At some point - 10 years, 15, 20... maybe the knowledge gap gets way too big for the current team - then get proactive.)


The real disaster is management. This thing was working perfectly, and therefore was ignored. Then it became a frantic crisis because nobody saw that some other change would break it.

And then they responded with an absence of reality. A two-week deadline that can't be moved? Um, no. Ever hear of reality? You might visit there sometime. It's a bit harsh on people with ridiculous demands, though, so adjust your attitude before you go.

And then, nobody can fix the existing one? You not only have the ridiculous demand, you rule out the only possible way of meeting it? What do you think is going to happen, the elves are going to work all night to magically create a solution?

This sounds like an epic management failure from start to finish.


> But how would the first response be "throw away all that investment and start from scratch" instead of "dig into how it works"?

Because start from scratch is more predictable ("estimable") than "dig into how it works". "Dig into how it works" is better in the long run, but will take longer. All software management is laser focused on speed and predictability rather than long-term quality.


Two terms you may want to refresh your memory on: second system syndrome and Chesterton's fence. I've never seen a rewrite come in remotely on time, and I've seen quite a few fail altogether. Often what happens is, in trying to solve the problem again, the developers come to understand the original system, which already works. It becomes impossible to articulate tangible benefits for the rewrite and it gets shelved.


"Dig into how it works" may take longer than rewriting or it may not. And the rewrite may (and often does) run into unexpected difficulties too.

I think it's a mistake to make the "fix the old" or "rewrite from scratch" decision up front from a position of high uncertainty about the old system.

I'd go with a strategy of starting a timeboxed exploration of the old system with the objective of understanding it better, hopefully well enough to have a reasonable idea of what it will take to fix it. Then make the decision from a better informed position. Yes sometimes the decision may still be to rewrite because you now know that the old system will be excessively hard to change but in many cases you may find out that the old system wasn't as bad as expected.


This is exactly the case where I think starting from scratch is the most difficult to estimate. This thing we need to update is a mystery-box, right? You don't know the code. You don't know all its edge cases. Tons of potential bugs could be introduced (or re-introduced) if you change it in the wrong way.

Replace-from-scratch has all the same risk of getting things wrong because of that lack of knowledge and a bunch more new-code-writing on top of it. Estimating new development often fails; estimating it in the face of business requirement uncertainty is even worse.


Can you quantify that to the management in that case?

To certain styles of management focused on "always building new products" to guarantee their worth/value, they absolutely will get blinders on and believe "new products are easy and more predictable than maintenance of old products". Those blinders are hard to take off once they get into that sort of pattern. All of their processes are built around "new products". That starts to be the hammer that wants to dismantle old products because they don't do maintenance (that's someone else's problem) but they surely know how to build new products. They are the build new products group, that's what believe they do. Building new products is exciting and they can be passionate about it.

I also think that's generally the wrong way to work and does plenty of harm and creates a lot of unnecessary stress on development teams caught in those cycles. But I've certainly seen plenty of management teams that do work that way in the real world and maybe don't question it enough.


Rescuing everyone with a shiny new system also takes more resources and looks (as you kinda note, too) a lot more like a real project, so product managers and project managers and various other managers can get comfortably involved and do their thing, with plenty of people to manage (= more prestige) and new UI to show off in powerpoints (= more prestige, doesn't even matter if it functions worse than the old one) and ordinary, regular development milestones.

Learning the old system enough to keep working with it, meanwhile, looks a lot like a couple developers staring at screens for months without results that look impressive to anyone who matters (as far as granting rewards goes) and with very uneven progress. Plus they've gotta be pretty good, experienced developers (so, likely expensive), or the risk of breaking shit as they begin trying to change the system, goes up a ton.


I'd like to disagree with you there, because of this one data point ;-).

I worked on an application where I knew just enough to make spot changes, while the other developer who had made the most core changes continued on with the core. Then he left.

So as more core changes needed to be made, none OMG due to Production issues, that made me dip into more and more of the legacy code, and I grokked what was going on. I wasn't happy with it, but I understood it enough to know that to make it truly maintainable would require a total re-do. But the code that was there worked, and as time went on I even took other developers' bolt-on additions and made their functionality take advantage of the sub-optimal idioms the core used, so that at least if someone else had to make changes, they'd only have to deal with one pattern. I've made wiki pages to describe it, but still any other developer who works on it ends up asking question after question and complaining why the documentation isn't in the wiki (it is; they just don't want to look).

We eventually moved to another servlet container, and I filled in the missing functionality the new server lacked, still keeping the original core code.

I've done that with two other applications at our company as well. Why haven't I moved on? Hey, I'm older now, and it's an 8 to 5 job you can't easily find any more.


It's not "gone", it served its purpose. Software is born, lives, and dies. By the time a project is 3-4 years old, unless it is a core central service, the business (if it is competing successfully) has most likely moved far beyond the initial assumptions laid out at its' creation.


It sounds like you haven't been in the situation the parent is describing.

I have and still am. We have stuck one ancient piece of software in a docker container and have our fingers crossed that it continues to work. This software is OLD, early Perl 5 old. Nobody in the department understands Perl or wants to. The business (read: product owner) has deemed it unimportant to update or understand, but I assure you that if it stopped working, it would affect millions of tax payers, upper management would find out (read: VP, CEO), and heads would roll.

Everything is fine, until it isn't.

Your thinking from the perspective of a startup might be true, but from the perspective of a company that is many decades old and has a dozen layers of management... perhaps not so much


This is absolutely a failure of management. Both the general management and _especially_ the engineering management.

Eng management needs to convey that this is an Achilles' heel that is important to understand & be able to update.

No engs want to work on perl5? Bribe existing employees, hire someone who wants to work on perl5, or a darker third option.

The product owner can even spin this as them doing a good thing to future-proof the business, even if it means their team loses velocity on other projects.


Nobody in the department understands Perl or wants to.

And that is the problem.

I don't know how bad that code is - a lot of Perl code from that period is not good - but learning enough Perl to have a shot at it literally should take a competent developer a few minutes if you had someone explain it to you.

You might find the language weird. $ means "the". @ means "these". % indicates you're building a lookup. Which you then access with braces. So %foo is a lookup. And $foo{$bar} should be read "the foo of the bar...".

Early Perl 5 means it probably doesn't use references or objects. You do use regular expressions. While regular expressions are built into Perl in a way that makes them easy to use, Perl-like regular expressions are in pretty much every language. So the effort you need to use them is directly portable to Python, JavaScript, Java, etc, etc, etc.

Fluency takes a lot longer. But getting to the point of "I can puzzle my way through a language I don't know well" should be doable very quickly. And it is a skill that every developer should build. Because I guarantee that whatever language and toolset you are using now, you'll need to be able to switch at some point in your career. And practicing in advance will help you. Plus being the person who can puzzle out old ganky code in another language lets you be a hero in fun ways!


> And that is the problem.

No, that's not the problem.

> the business (read: product owner) has deemed it unimportant to update or understand,

That's the problem. It's not on a random person in the department to spend their own time trying to solve a problem the business doesn't want invest time or money into solving. I don't see you offering to do this for free, so don't claim that's a problem for others.


I've been around the block enough to read between the lines on this one.

All of the talk about how old and bad the language is, and how nobody wants to learn it is tech speak for, "We can't support it as is, we need a rewrite!" Anyone who has been near tech for a long time knows "rewrite" means "tech is going to break it for unclear reasons and uncertain gain, and in a few years will want to rewrite it again. Tech people always underestimate the cost and risk of a rewrite, and also overestimate the benefits.

Business is not being stupid in saying that tech can't rewrite the software. The software is there, works, and is being relied on. Tech should figure out how to support it without a risky rewrite. Don't stand on, "We don't want to learn Perl." Learn how to be a polyglot. At least when it comes to reading. And to the extent that tech understands the value of being prepared, tech should prepare in advance. And figuring out how to read the code is most of that battle.

Now you accuse me of not offering to do this for free. But in fact I offered the best tip I could for a non-Perl programmer who is trying to puzzle their way through an early Perl 5 script. Given that I'm an internationally recognized expert in Perl, that tip probably does more good than you realize. Learning how to navigate legacy code in a legacy language is a learnable skill. And you learn it by trying, then finding you can. And no matter how much you don't wish to learn any particular legacy language, having the confidence to know you can is valuable.


> All of the talk about how old and bad the language is, and how nobody wants to learn it is tech speak for, "We can't support it as is, we need a rewrite!" Anyone who has been near tech for a long time knows "rewrite" means "tech is going to break it for unclear reasons and uncertain gain, and in a few years will want to rewrite it again. Tech people always underestimate the cost and risk of a rewrite, and also overestimate the benefits.

No, it really isn't. I'm happy to learn a new language. The reason is correctly stated by a sibling post here (WesolyKubeczek).

That we've been able to containerise it has limited a lot of the risk, and any upstream issues we have going forward we should be able to write some middleware to sit between it and transform the data into the format we need. We can extend the container to proxy any requests from the ancient application to the new middleware. We have a strategy, the product owner is happy with that, but we've outlined that maybe the solution won't work as we think, there are always unknown unknowns...

The issue is that if a problem does arise, it will be immediate and the effects will be there for as long as it takes to get a fix up and running, which could be weeks to who knows how long. That's a real risk in my eyes, but it wasn't to our product owner.

It will affect a lot of people, it's a pretty widely used service! It's entertainment, so people won't die if it fails.

The risk was deemed low enough by the product owner that we can just leave it in a container until it's finally sunsetted in 5-10 years (or so...). We've had 2 product owners since the OG product owner made that decision, so it could just be the product owner who made the decision thought they'd be long gone by the time it became an issue.

You're making assumptions about people you've never met, you don't know me and you don't know what motivates me.

You aren't as good at "reading between the lines" as you think you are.

---

From your profile: My main programming language is Perl

Oh, it all makes sense, you're hurt that I called Perl 5 old! That's funny. I've never written production Perl, I am not making a judgement on the language.


God help you if this is Rentrak.


Who or what is Rentrak?


> Because I guarantee that whatever language and toolset you are using now, you'll need to be able to switch at some point in your career.

Yeah, but the motivation to learn Perl 5 as your next language is about as wise as learning COBOL as your next language.

That's probably why parent is finding it hard to get his developers to work on it - lots of effort for negative gain[1]. Anyone wanting to learn Perl 5 in 2023, for no additional money, is probably legitimately crazy.

I don't understand why you don't see the problem that parent has - no one wants to learn Perl 5 because it is a dead-end, and takes up energy that would otherwise be spent moving your career forward.

[1] The opportunity cost is immense - the time used to learn Perl 5 enough to maintain the legacy code is time that could have been used to learn a current language that results in a payoff.


>It sounds like you haven't been in the situation the parent is describing.

Sure I have. And the first few times I too thought that it mattered. But it doesn't. None of the stuff we care about as software developers actually matters. We are just pawns for the people making money decisions. Completely replaceable automatons. If what you are doing is not directly supporting a strategic business goal, you are doing nothing but costing a business money. And cost centers are the first to be cut. You can sit there with your sense of self importance, thinking that the cleanliness and elegance of your code matters. But it just doesn't. Nobody cares. And the sooner you let go of thinking it matters the sooner you can focus your effort on what does.

The reality is that when whatever old house of cards you're running fails for whatever reason, the business will switch to a vendor that covers 95% of the use case, while being much cheaper and not requiring FTE support. It will be a tiny bump in the road for the business, replacing this thing that you thought was a world beating make or break technology.


What would be an example of such a software company?

I am always faced with this issue with non-software companies in industries where I've worked such as nuclear, defense, energy, and healthcare. At these places, I've confronted "hands-off" modules that are effectively black boxes of complex logic that has been vetted over decades, is written in C or Fortran, and nobody is allowed to modify.

I can't imagine that situation existing in a software company.


In my haste to give an example I missed the part about it being for only "software companies", we're not a software company, but we do have a lot of developers


The problem that your product owner cannot see any value in replacing/understanding/modernizing that piece of software, but should it fail, the heads would roll, speaks of a bigger problem in your organization than an ancient piece of software.

You have been able to put it in a container and it’s running, so unless the kernel itself changes drastically so old libc will just stop working, it’s going to be able to work unchanged for a decade more.

But the communications problem between management layers is way bigger than that, and could probably bite in some other situation.


> This software is OLD, early Perl 5 old

Heh, it never fails to crack me up how relative old is. I’ve worked on software that predates Perl, and even UNIX itself…


That's amazing! Can you share more about what sector you are working in and what the software in question does?


3-4 years is very short as far as software lifespans go. Software libraries that are 10-15 years old are commonplace in both open source and at FAANGs, and some industries practice "extreme longevity": any domain where you wouldn't be surprised to run into a mainframe is probably also running code with a 30 year+ lineage.


I don't think it's a coincidence that software lifetime has converged to the time it takes an initial stock grant to vest.


Don't know what kind of projects you are working on, but in the world where I work, source-code that is literally decades old is common, and companies pay extremely good money for people who understand it.

This includes things like airline reservation systems, scientific computing models, compilers for obscure dsls, and the like.


If a business is competing successfully I don’t think you’re going to see software obviated every three years. Software isn’t like living beings that up and die. They evolve over time.

Companies doing rewrites every three years have a hard ceiling.


> it served its purpose

That's a blind jump. We don't know the purpose, we don't know how much was invested, how much was already recovered, and how much more could be earned if the program was allowed to live.

All we know is that it has recently hit fitness to purpose, and that the fitness caused it to be abandoned.


Fun story about the 3-4Y window, one of the execs at my company was having a Q&A, and he gave an example in another question a new set of components, saying that he expects them to be in use for the next 20Y. I asked why does he think he can keep the know-how and outsmart the competition (components were part of algo trading and other trading related things) for the next 20y with just this investment, and he just downplayed my question as an IT guy wanting more money/work. ¯\_(ツ)_/¯


Related to Naur's classic:

Naur on Programming as Theory Building (1985) [pdf] - https://news.ycombinator.com/item?id=31500174 - May 2022 (4 comments)

Naur on Programming as Theory Building (1985) [pdf] - https://news.ycombinator.com/item?id=30861573 - March 2022 (3 comments)

Programming as Theory Building (1985) - https://news.ycombinator.com/item?id=23375193 - June 2020 (35 comments)

Programming as Theory Building (1985) [pdf] - https://news.ycombinator.com/item?id=20736145 - Aug 2019 (11 comments)

Peter Naur – Programming as Theory Building (1985) [pdf] - https://news.ycombinator.com/item?id=10833278 - Jan 2016 (15 comments)

Naur’s “Programming as Theory Building” (2011) - https://news.ycombinator.com/item?id=7491661 - March 2014 (14 comments)

Programming as Theory Building (by Naur of BNF) - https://news.ycombinator.com/item?id=121291 - Feb 2008 (2 comments)


Here's a more readable version I came across: https://gist.github.com/nwh/60eb3115754e68f2d1c46aa31961b660


> Accepting program modifications demanded by changing external circumstances to be an essential part of programming, it is argued that the primary aim of programming is to have the programmers build a theory of the way the matters at hand may be supported by the execution of a program. Such a view leads to a notion of program life that depends on the continued support of the program by programmers having its theory.

Agree with the theory of programming as theory*, but here's the problem with that essay in an era of software-as-a-services and platforms:

A SaaS offering or an Enterprise runs on a stack or assembly of software, each of which has its own Theory.

The problem with no churn is that most of the Theory is not in-house, it's elsewhere, and evolving. If you can't tap into that, you're falling behind. If you don't know it, you can't remix it into your own.

It's just math to convert an org's "refresh rate" of outside-in knowledge (aka churn) into the average lag of that organization behind current best theory and patterns. A 10% churn means an average of 5 years out of date. A 20% churn means at least a fifth of your org is 5+ years out of date.

A couple key antidotes, though (and there are of course more):

Realize that knowledge transfer from (a) outside in, then (b) among, is vital to theory maintenance and evolution.

That means (a) have a great "always be hiring" pipeline of fresh Theory and build processes to make knowledge sharing of outside and inside theory frictionless and routine, and (b) have a great "always be learning" approach to exposing developers not just to the internal theory but to the best and most up to date outside theory.

The better an org is at (b), the less it needs (a). The worse it is at (b), the more it needs (a), but -- crucially -- it must refresh with candidates who know more recent theory than the ones doing the hiring!

Churn is not bad, that word is spin. Internships are a thing, so are externships (firms should do more of this). People, and theories, grow by exposure to novel challenges. Circulation is good for the whole ecosystem of software development because we are building a collective Theory bigger than any one org.

This remixing of ideas is how our collective Theory evolves.

* Most recent decade of my career involved a lot of evangelizing to enterprise management that developers are not project teams to form and disband as fungible resources. Think in terms of capabilities to garden, not projects to remediate.


> This remixing of ideas is how our collective Theory evolves.

compare https://news.ycombinator.com/item?id=34315203 (and its wider context)


The biggest problem is that software companies don't see "software development" as theory-building. Instead, they see "software development" as solutions to plumbing problems; that way, they can call a plumbing company at 1-800-CLEAN-ME whenever new problems emerge.

Even not many people subscribe to Peter Naur's "Programming as theory building"[0]

[0] https://pages.cs.wisc.edu/~remzi/Naur.pdf


I have plumbers in my apartment right now fixing a leaky drain pipe between two floors. The first thing they did was show me why they were going to need to rip out a 10 foot length of ceiling and re-do a whole section of pipes to fix the leak because the previous plumbers did such a wacky job.

So I guess it doesn't actually work for plumbing problems either.


> they can call a plumbing company at 1-800-CLEAN-ME

And, in fairness, that is a reasonable thing to want. The problem is it's not clear whether or not that's possible, and it is clear (but completely ignored by the people who ought to be aware of it) that our current software development methodologies don't even come close to allowing it.


> The problem is it's not clear whether or not that's possible

It's not.

Attempting to say it is is very akin to wanting a single, pre-created bridge to be able to span any valley. But valleys come in all shapes and sizes, and so too do the bridges required to span them.

Certainly, there are some parts that are the same. I think most of us complain about cookie cutter CRUDs or byte shuffling, but even in all that, there's generally some higher purpose business reason as to why the software is doing the byte shuffling that I am, or more deeply, why the software is doing the byte shuffling the way it is[2].

And honestly, I think that oversimplifies it, when it comes to the problem and the software that attempts to solve it. The problem can and often does change in software … so it's akin to a valley that shapeshifts, adds new local laws of physics, and requires the bridge to change and adapt. How changes to the software mesh with the existing software, and why that might be — is unique to the project. (And, as Naur argues, contained only in the heads of the developers, and what is in their heads is not even necessarily the same.)

[2] And to extend this with the shifting valley analogy, when new byte shufflings come along, would they benefit from this program's current design? If I need to extend the design, would a given extension work well? Are the requirements different enough that I need to consider something separate for this new requirement? etc.


I've long felt that this is an issue unaddressed by the industry, though I've framed it as "knowledge acquisition and dissemination." As part of building a software product, the developers acquire deep knowledge of both the problem being solved and the system that solves it. The question then becomes: how do we efficiently capture and disseminate that knowledge?

Capturing the knowledge is expensive both initially and over time as the software itself evolves. Disseminating it is expensive because it costs O(NM) time, where N is the number of people receiving the information and M is the average amount of time taken to absorb it. Dissemination is so costly, so we tend to do it in a "lazy" manner, meaning non-strict or as-needed.

I think the best software systems I have worked on do a number of things:

1. They define enough ad-hoc proofs or invariants via unit tests. It's possible to work around these by simply disabling the tests, but, assuming your team hasn't devolved to that point, the tests are an excellent source of machine-readable and machine-executable knowledge.

2. The software is designed modularly so that one can operate on a part of the system without having to understand the entire system or worry that an unrelated part of the system is going to break.

3. The system is kept as simple as possible. The less knowledge one needs to accomplish the same task, the better! This is why KISS is so important. It's not for the person writing the code so much as the person debugging it a year later! As a corollary, a simple system tends to have less dependencies. Dependencies are actually costlier than people realize. Every dependency suffers its own bitrot problems and requires knowledge to handle them as part of maintenance.


The lowest hanging fruit on any project is always documentation. Dissemination isn't O(NM) if your docs are well organized. At least, that's been my consistent experience over the years. I feel like our industry approaches documentation today the way it approached testing in the 1980s, before unit testing became widespread and culturally accepted/enforced.

The problem is, just like how at the start you find lots of devs who don't want to write unit tests, you usually have a lot of devs who resist writing (and reading) docs. They'd rather interrupt someone to ask, or thrash around, or move onto the next task the moment some code is written.

What helps:

1. Keep your docs alongside the source, in version control. This lets you gate code reviews/merges on docs being updated. Someone changed the way the code works but didn't update the docs? Then the PR is rejected until it's fixed.

2. Leading by example. If the TL for the project updates docs with their code changes, and visibly spends time gardening the docs, then they can't be accused of hypocrisy when they demand the same standards of others. Praise quality docs work when done by others.

3. Make the docs beautiful. Let people have pride in their work. It's so easy these days with great static site generators.

4. Answer questions by linking to the docs when possible, not ad hoc Slack/email/ticket discussions. If the docs don't tell someone the answer ask them to hold on for a moment, update the docs quickly and then link to them. Obviously this requires a fast / lightweight turnaround process on review and merge of docs changes, but it can be done.

5. Avoid wikis. Quality requires ownership, someone who is directly responsible and can enforce their will. Wikis don't let you do that so they become a commons, and you end up with a tragedy. Use Markdown or equivalent in a VCS repo so you can refactor docs as they expand, make sure there's someone (e.g. yourself or a trusted lieutenant) who is expected to spend time paying down docs debt every so often.

6. Docs bugs should be a thing. File them. Expect people to fix them.

7. Make it clear that people are expected to read the docs, not just write them. If someone is regularly asking colleagues questions that they could have answered by reading, ensure that's treated like other performance issues i.e. their managers know and the need for improvement is clear to them.

There's more that can be done but these things do work. The biggest problem is always passive resistance. Just like with unit testing or code review, if a culture of avoiding it grows then you'll find it hard to introduce, people will passively resist because it's not as much fun as just banging out more code.

With these approaches the robustness of a program to churn can be improved a lot, you can scale teams up quicker and productivity improves.


I believe what you're saying is true, I just haven't seen it in practice. I've long joked that the best documentation is the source code, and, really, it's not so much a joke as a truism. I've found that having readable code has resulted in the best documentation I've seen, and you don't have to worry about it being out-of-sync!

I do believe documentation is important, but, having joined recently the largest corporation I've ever been a part of where I work on products of a larger size than ever, I am amazed to find documentation here to be as bad as, or even worse, than anywhere else I've worked, and most of it is simply outdated and irrelevant. I guess I need to work somewhere that does documentation well to believe in it more.

I also consider myself a good technical writer. Unfortunately, it seems that many software developers don't share this skill, and this could be a major reason why so many resist writing it. I think a litmus test for this is whether someone prefers to share information via a document, or via an in-person meeting, a conference call, or a video recording of a meeting. Unfortunately, videos and meetings are not searchable, indexable, updateable, or quick to scan. But they seem to be preferred by the same people who don't want to write anything down.


I've used that strategy a few times now, albeit mostly with "user" facing docs where the users were other developers. My current company is tiny but I wrote both internal and user facing docs from day one, so practicing what I preach. It's pretty useful. Writing stuff down is permission to forget and I often end up consulting my own docs, especially for procedures that only happen occasionally.

In prior projects I did it too and success was mixed. On one hand, the docs we got out of it were objectively great, as in, users complimented us on the docs regularly, they were a source of competitive advantage and we could tell they worked because users would regularly show up successfully using advanced features of the product without having asked us any questions.

On the other hand, creating a self-sustaining docs culture was hard. People would do it when faced with the expectation of doing it, and often the resulting docs were fine - tech writing isn't as hard as it's sometimes made out to be - but getting other devs to really buy into it and become docs evangelists themselves was much harder. Also of course you'd have inevitable team friction when someone really hated writing stuff and would have to be forced to do it, and then they'd submit min-viable or low quality work. No different to having a team member who refuses to write tests, of course.

I think this can be solved with time, with cultural change in the industry. One problem, and please don't take this personally because I'm talking really generally here, is the view that source code is as good as documentation. I feel like lots of devs convince themselves of this because they like writing code and don't like writing docs, but I never found it to be true in practice. Any time I have to use an API or tool that has tons of missing or obsolete docs my heart sinks, partly because rummaging through source code is slow and tiring compared to reading a well written document, and partly because it tends to be a proxy for low effort work in other ways. The claim that docs are always obsolete is self-fulfilling. If you don't put in place procedures to ensure they're kept fresh and good then they'll rot, and then that's used as a justification for not putting in the effort, so it's a vicious circle. Again by analogy to testing, competent teams don't just let devs comment out tests instead of updating them, it's just not culturally accepted in high-functioning environments. Same can be true of docs.


How do you reconcile your points 4 and 1? Say I want to answer someone's question on Slack. First I have to change the docs, but doing so would require a whole PR, alongside approval, which may take one or multiple days.


You can flip the order of the steps and it works pretty well imo: answer on Slack, and then once the discussion is complete, clean up the messages and put them into the docs.

This has the added benefit that you can have some back and forth to get to the root of the question before documenting it.

The key thing is that you have to make sure to actually do the step after (transfer to docs), even if it's a quick copy-paste with minimal editing.


You can point people at the answer in the PR, or you can relax approval requirements for docs changes, or you can be someone who actually can approve docs changes yourself. There can still be ownership in that model it just doesn't require pre-approval, only post-approval.


> That mental model can only be learned by having worked on the project while it grew or by working alongside somebody who did, who can help you absorb the theory.

Maybe it's because I've done so much reverse-engineering, but I reject that claim. It's quite possible to start with a binary ROM dump and build up the theory of the code. If you have source code that's even better. And the whole point of design documents is to explain the theory.

Curiously, the book quoted at the top of the article gets this correct: "Revival of a program is the rebuilding of its theory by a new programmer team." But the article says that the only way to rebuild the theory is by writing new code.


Certainly you can build a theory via reverse engineering. The question is whether the theory in your head matches the theory in the head of the person who wrote the code.

Naur's argument is first that there is a theory at all, and that the question of whether it can be transplanted to another person is really unanswerable. We can attempt to answer it, or build confidence towards an answer, by doing things like writing/reading design docs, having experience in the industry that shows us how other eng tend to think and design, talking to the person who wrote the code, testing our theory against the code, etc. But we can never be certain of what is in the mind of another person.

Anyone whose ever taught anything to a student, I think, has come to see this. It's hard enough to teach people how to do a thing in response to a known circumstance. The real trick is to teach them well enough to have them extend their knowledge on known circumstances to new and unforeseen ones.

And Naur, IIRC, also argues that churn is inherently bad, and that programmers are not replaceable cogs, because one of the valuable contributions they are making is holding, in their minds, the theory of how the code solves problems:

> More generally, much current discussion of programming seems to assume that programming is similar to industrial production, the programmer being regarded as a component of that production, a component that has to be controlled by rules of procedure and which can be replaced easily


Reverse-engineering is inherently an inductive process, whereby you have to make educated guesses as to what the model is, iteratively.

Samba is a great example of how this is necessarily an imperfect model, and definitely not an optimal process:

- https://news.ycombinator.com/item?id=488089

Development as theory-building is intended as a metaphor to understand the impact of the collaborative mental model that is created as part of any complex system, and the losses incurred when this mechanism is not appreciated.


Having worked on reverse engineering complicated proprietary network protocols (but not for a long time), this is true to an extent. The “mental model” developed may not match the original authors in the exact way intended, but a working model can be constructed none the less.

We were often able to make better models than the assumed original authors (at least the software that used said protocols was much more performant due to better packing algorithms), so I’m unconvinced that reverse engineering puts you in a worse state.

Fully agree that the cost of reverse engineering is large, requires exceptionally skilled people, and no company should ever willingly put itself in the position where it becomes necessary for their own software.


Yes exactly. It’s reverse engineering. That doesn’t mean it will be easy, but once the reverse engineering is done you are back to where you were.

Anecdote: Worked for a company that had a large software component (graphical design tool) that had been written in C with a very complicated object model/macro layer, file system format etc. Zero documentation, hadn’t been updated in a decade and not a single person remained who understood it or had done more than simple bug fixes. Couldn’t rewrite as customers had huge investments in assets built from the tool.

One principal dev and maybe 1-2 months? And we had the theory of mind back, explained to everyone else and a new team of 5-6 devs working productively. Component was brought into the 21st century, and this time some documentation was written.


It's been a while since I've read the original paper, but that is my recollection of it.

That if a new team takes on a codebase, they are rebuilding the theory and reviving the program.

The new theory may not be exactly the same as the old but it is probably still adequately compatible.

In a sense, the new team is reverse engineering the theory, from the source code. Even though this is a much easier task than doing so from a binary.


The paper's conclusion is stronger: a new person on a still existing team is rebuilding the theory. Albeit much quicker and with much higher confidence, since they can talk to the existing devs and learn directly from them, but they're still having to build their own theory, separate from the original. (As we don't have SFTP between brains, yet.)

> A very important consequence of the Theory Building View is that program revival, that is reestablishing the theory of a program merely from the documentation, is strictly impossible

> […]

> Similar problems are likely to arise even when a program is kept continuously alive by an evolving team of programmers, as a result of the differences of competence and background experience of the individual programmers, particularly as the team is being kept operational by inevitable replacements of the individual members.

Reading documentation & talking to the original dev are inherently the same thing: we're using some medium (written docs, spoken word) to attempt to convey information.


We're working on a project that was inherited from previous engineers with no crossover. The first thing we did was write an end-to-end integration test suite for all the features we could find, which has grown more comprehensive over time. We still have old code we know is working alongside newer code written in a completely different style. We've been able to make major changes in tools and conventions over time while keeping progress steady. While we'd love to clean up all the code and have a single set of the latest conventions the decision is always refactor it now or maybe punt and we'll get to just delete it later, we usually go for the latter.

I think the biggest benefit has been that the tests are isolated from the implementation details so we can always be sure everything is still working without having to refactor the tests themselves.

There is still a learning curve for new people because they don't know which of the multiple conventions in the code are the presently-agreed-upon ones, and that is where we could probably use some better documentation, but I think the end-to-end tests really saved us from the idea that some knowledge is lost and we might need to start over.


Yeah, zero doubt investing in robust, automated E2E tests in that situation is key. I’d also add:

- Get the “change engine” running smoothly (productive and reliable local dev environment, reasonably fast/reliable build/deploy jobs)

- Get people understanding, documenting, and teaching others the high level functionality and architecture

If you skip those steps, and hop straight to new features, you’re just asking for regressions, outages, poor architecture/design decisions, and just a very slow pace of work. But invest in those 3 up front and you can get to a point where you’re evolving the product well, with few regressions, at a good pace, even without vets to teach the newbies.


People joke about militaries writing docs about the exact number of turns each screw can take, but a-10 are still airworthy and the last one was built in the 80s

Quips aside, software life expectancy matters, so total documentation approach is not something that works for everything. But if your software has generations of developers, maybe it's worth thinking about it.

That or a total rewrite every skip generation. I can see both working, and maybe total rewrites are a better approach in a world of ever changing requirents.

Thing is, documentation is great to capture static knowledge, and a evolving software is not static by any means

If I had to pick and choose, I'd say written requirements with change management for every domain object APIs within the software object model, and anarchy underneath.

The code conforms to the requirements, and not the documentation conforms to the code, so to say. Contract driven, in a way, but only where it's relevant.


> Thing is, documentation is great to capture static knowledge, and a evolving software is not static by any means

There are many open source projects with great documentation and they manage to keep abreast of changes.

This attitude among programmers that documentation is hard, so don’t bother is just that - attitude.


> and they manage to keep abreast of changes

With varying degrees of success.


the documentation for something like angular or rxjs is about how to use the framework, the documentation doesn't explain the underlying code...


This blog does pretty good job summarizing Naur's points. (My only quibble is equating mental models with theory in Naur's sense, but its an okay approximation). I definitely recommend people read the original paper. It's a flawed but beautiful paper.

Shameless self plug:

We just did an episode on Naur's Programming as Theory Building in the most recent episode of the Future of Coding Podcast.

https://futureofcoding.org/episodes/061


I was going to post this! I really enjoyed this episode (and also, all the other episodes of your podcast).


Can you elaborate on why you think the paper is flawed please?


I think all papers are flawed in their own way. So it is not meant as a slight. It is actually my favorite programming related paper. That said:

I think Naur was just a bit to vague and assumed background knowledge of Gilbert Ryle where most people don't have any. I think a lot of people finish reading the paper and don't realize what Naur's notion of theory is or how his radical conclusions follow.


I don’t know Gilbert Ryle but I believe I understand the paper as intended.

What do they realize then instead?


When I first decided to get into web development after taking a couple of years off from software (after doing Java development in the finance world) I started with Ruby on Rails because it was hot at the time.

I spent several weeks going through about three books on Ruby on Rails and working endlessly on tutorials, etc. But I got nowhere and I couldn't stand it.

Then one day I read the Django documentation and it took a completely different approach. The approach that the Django documentation took just made sense. It began by explaining what the problem was from a high level and then explaining different solutions that had been tried over the years and what their drawbacks were and how this led to further approaches, and so on. By walking me through the system that way it made Django clear and sensible to me.

All the Rails stuff I had been reading seemed to assume that I already knew everything but just needed to understand some magic incantation. Django treated me like a child, which meant that it actually treated me like an intelligent adult.

I'll never forget the experience of reading that Django documentation. It was crystal clear and it changed my life.

This all happened around 2012.


This all makes sense to me, but how do you reconcile it with the fact that job tenure in Silicon Valley tends to be so short? (Like, people hopping jobs every few years?)

* If churn is lethal, shouldn't we expect the center of the software industry to be in a city where people take a more conservative approach to their careers, sticking with a single employer for 10+ years?

* If churn is lethal, wouldn't we expect a stronger focus on retention of software engineers? Instead, it's common to offer new hires generous packages, and common wisdom is that constant job hopping is the path to high compensation.


The most valuable software tends to be written by people who commit to their work.

The frequency of job hopping is inversely proportional to the time spent working on a career.

Gaming the system for a large salary early on without much experience only hurts the employee with burnout and getting replaced with better developed talent more deserving of the role.


There's the theory and there's reality: resources being limited and a finite employee can run things at any time, companies have to compete for their survival by hiring high while killing their competitors.


I've got a little pet theory related to this. Which is that no one really solves difficult problems. They turn difficult problems into easy problems and then solve that. Often that literally means "We have this class of problems, I'm only going to solve the easy subset". And I've observed repeatedly people say "No we have to solve the real, hard, problem" - and a decade later, with a team of a hundred engineers, they've not really got anywhere.

Applied to this, that theory is very simple. It's enormously difficult and expensive to keep old code running, especially when the engineers who originally wrote it have left. Not only is it difficult, but the engineers who have to do maintain it will hate it, churn themselves and you'll be back to square one. So, solve the easy problem. Get your new guys to write something new, and give up on the old software once all the people who knew how it worked quit. And it's easy! No one left at the company is going to argue to keep the code. The new people will enjoy writing something new. Oh and people will be amazed at how happy and productive your team is - because you literally just choose not to do things that are difficult and no one appreciates.

But you may ask, what if the product is essential, you can't just abandon it. Well, call me flippant but if it were essential you shouldn't have let the engineers quit. And if you're really going to saddle me with it, I'll quit too. Then you still don't have your software, and it's not my problem - it's yours.


> They turn difficult problems into easy problems and then solve that.

I think this needs to be said more carefully. For instance, problems could become manageable when a well-thought-out mental model is built. On the other hand, they could become easy when the problem itself is simplified. For me, the e-voting problem fits quite well in the picture where thousands of systems are being built with cute mobile UI but, in the end, are really holding on to the assumption: trust us, we will be honest.


If it’s essential it could last decades, greater than the career length of a developer. What happens then?


Successful products are like the ship of theseus, they can go through the hands of thousands of engineers, the important part is having people actively working on it overlapping with more experience people. You don't literally expect the original author to be there forever, butyou do expect people to come onto the project and learn about it whilst the more experienced people are still there. If literally everyone working on a project is gone, the project is probably unmanageable at that point anyway, there's no point starting CPR, the project is dead.


I guess you budget to rewrite it even though it's "working fine"


This happens even if I step away from my own code for a few months.

The last program I built was coded around characters from Sherlock Holmes, by making the code like characters that had to interact in a certain way, it helped me maintain a mental model over a longer time. It genuinely made the code more enjoyable to work on, as it is a story now


A myth, a plan, a canal.

I worked for a period in a consumer product OT shop. I was a consultant; not a 2nd gen. It's not often you discover you have access to a quarter $mil of OT equipment just lyin' around as hot spares sitting in a lab down the hall; and it all talked to the hot spare L2 which we used for development.

Technically, I was working on the L2 system. But I needed to write test plans. When I showed up, they showed me "the wall" which was three ring binders (1/2 to 1 inch thick?) of "test plans". Each binder was a test plan. Yes.

Over the better part of a month I assembled enough stuff in the lab to run product "end to end" in the best environment we could simulate.

So, after meetings, I was able to write a test plan which referred to an SOP for some portion of its setup and then deviated (a "variance") for the actual test. Tests took longer to execute, but a hell of a lot less time to write.

To set this up, I interviewed the actual line personnel. By the time my tour was done I had to schedule time in the lab because they were using it for training and general "what if" screwing around.


When Twitter was still in managed hosting and basically out of space to put new equipment we started an emergency "build a datacenter" project of which I was initially one of the only FTE's allocated too it. My plan was simple: I don't have bodies to throw at problems (we didn't even have data center techs and our facility was still under construction) so my plan was to make something that could effectively "self deploy" a functioning data center for us.

I locked myself in a really hot closet behind the cafeteria with several pieces of our soon to be purchased hardware and started coding. The whole thing ended up amazing and I am still proud of it to this day. =)

Some of my primary goals where simple: No manually edited configs, ever. If you swap a mother board there should be no mac address tracking, no serial number editing, etc. If we can detect it automatically we did and updated the machine database automatically. Hardware techs could simply walk out, swap a drive, and walk away and we would track that.

So we wrote a tool called vex that would export all the machines various bits and bobs. Anything we could access, serial numbers, mac addresses, etc. So once the machine was running we knew where it was, what it was doing, etc. The biggest challenge was getting it running in the first place. The plan was to use DHCP option 82 which includes port information when forwarding DHCP requests to an upstream server. Thus our dhcp server (written by an awesome coworker in like two days) was 100% stateless. It knew the IP range for the datacenter, the ip range for the rack, and the port that the request came from and could respond with a static IP every time. Swap the mother board and it wouldn't matter because the machine would still be plugged into the same port on the switch. Each machine would then request a tftp boot image from the server listed in the dhcp reply. This server was smart, it would look in the machine database to see what state the machine was in and where it needed to go "next" so to speak.

Step 1) Machine has never booted before. It would go into an identify utility that would allow the installer to verify that each machine was plugged into the right ports. The tech could watch the ipmi identify lights on the machine as it activated each in the rack in order and if any where out of order network cables needed fixed. From this point forward we knew that port 3 was the 3rd machine in the rack on the prod and ipmi networks. Once identified the machine would automatically reboot.

Step 2) The machine would run memtest86 to ensure that memory was valid. Sadly I didn't have time to make it automatically update with results and reboot so this step required manual verification when I left. A engineer would check IPMI and mark the test successful.

Step 3) The machine would run stressapptest to push the CPU and memory to the extreme. This allowed us to ensure that they would not overheat and that the rack could pull the load needed to get all the machines to 100%. Once done it would mark itself successful and reboot.

Step 4) The machine would run fio to ensure that every attached disk was in good state and fully functional. Again, it would then reboot automatically.

Step 5) The machine would install our default operating system assigning hostnames and such via parameters from the database.

Lastly once the machine booted into its "real os" for the first time it would setup puppet, install all the back packages, look into the machine database for its assignment and then install all the various bits ad bobs required for it to do its selected function (hadoop, web server, dhcp server, puppet server, etc)

Everything was driven by the machine database, and you could mark a machine as needing burn in and it would repeat the testing steps. Super useful if you suspect a machine is bad in some way but don't have time to debug. Once running vex would export all the details of the machine as well so we could track failure rates, hardware events, etc.

Best part is that the lab ran the same software as the datacenter so we could always test the various bits of this process to see what worked and what didn't. In fact I added several optional steps to do things like get performance profiles and build all kinds of cool graphs from tests on demo hardware.

I ended up bootstrapping three datacenters and all it required was an "Ark" which was just a single server with puppet, dhcp, tftp and audubon on it ready to setup all the other servers in the facility. During our initial power up we had a DHCP server doing something like 100-500 requests per second sustained over the course of like a half an hour (until the memory tests started)

Sorry, not sure why that memory jumped out at me but it seems you did something alike and it reminded me of how much fun it was to be involved in mine. =)


I had to be walked down the hall several times to the lab before they'd let me do it alone. Forklifts with loads that would crush you and ruin production. It was ritual, on so many levels. Interviewing the Level 0 meat...

I think this is about myth and ritual. Resist the impulse to build it to something other than the Building. There wasn't any "cloud" in Colorado in the 1990s.

"People lose focus" is an anodyne when they never risked their lives to begin with.


I suppose that's not very clear. Somebody built a (very special) product packaging line. The people who built it moved on. There were still engineers doing maintenance (level 1), but changes to the control system (level 2 in the Purdue Model) were almost nonexistent.

Once the line was built, the meat moved in to operate it. In fact, the meat had standups: it was the first time I ever experienced a standup (and I wasn't meat, so I wasn't invited to speak unless I submitted an agenda item ahead of time).

The meat knew how to operate the line (and operate it safely). Although the culture of safety and quality was everywhere, the operational practicalities had been lost at the control system level: the meat were the experts, and we asked them questions a lot. But nobody asked questions about how to run the line, because nobody was going to change that ever!

So those were the kinds of questions I asked the meat and the level 1 engineers in order to construct an end-to-end simulation in the lab. It created a relatively safe shared environment where people could perform experiments and test their understanding of how things worked and appeared to work at the different levels.

The level 1 engineers were a pretty easy sell and helped a lot. The meat were generally willing to answer questions, and moved in once they could see it working. I actually authored the SOP by typing up HTML docs in Notepad on a file share. HTML was a new thing for them.


What does “OT” mean in this context?


"Operational Technology" -- what IoT wants to be when it grows up.

PLCs, custom electronics, servos, consoles with switches and knobs, very expensive printers (probably running Windows unfortunately).


I have only limited experience but I think the worst thing you can do when taking over an startup (with the intention to continue it) is to start with firing people. I know it's expensive and not always viable but you should try to "let it operate like normally" while auditing it before starting firing people.

Like some especially stupid examples:

- firing the main tech lead which had worked month of unpaid overtime (not for month, but the accumulated equivalent of month of work) because he supposedly didn't work enough during the insolvency proceeding/first week after it.

- cutting the cost of renting the storage system with essential data without making backups

- firing most people which where important for the main product

- firing people in such a bad way that most of the rest quit, too

- deciding it's more important to keep marketing people then people from the development team in a situation where the insolvent company had multiple bigish contracts they just where missing a few month of work to be able to deliver to and interests from other customers and the buyer being the main potential customer buying the company to get the product


The Tacit Dimension, Michael Polanyi, 1966

https://press.uchicago.edu/ucp/books/book/chicago/T/bo603536...

Programming and Tacit Knowledge

https://mbuffett.com/posts/all-tacit-knowledge/

Tacit Knowledge blogpost series, Commoncog

https://commoncog.com/the-tacit-knowledge-series/

Acquiring and Sharing Tacit Knowledge in Software Development, 2013

https://www.researchgate.net/publication/264125152_Acquiring...


I'm curious what you see as the connection between this article (which I think captures something very important) and the "tacit knowledge" concept (of which I'm very skeptical, having read Michael Polanyi's book and a bunch of the secondary literature).


“ What keeps the software alive are the programmers who have an accurate mental model (theory) of how it is built and works. That mental model can only be learned by having worked on the project while it grew or by working alongside somebody who did, who can help you absorb the theory.”

wiki says:

“ Tacit knowledge can be defined as skills, ideas and experiences that are possessed by people but are not codified and may not necessarily be easily expressed.[5] With tacit knowledge, people are not often aware of the knowledge they possess or how it can be valuable to others. Effective transfer of tacit knowledge generally requires extensive personal contact, regular interaction,[6] and trust. This kind of knowledge can only be revealed through practice in a particular context and transmitted through social networks.[7] To some extent it is "captured" when the knowledge holder joins a network or a community of practice.[6]”

The distinction appears to be the implication of OP that the ‘theory’ is not communicable, thus “first generation” workers need to be around. But you can clarify (am interested in your views) (a) what’s your crit of TD and TK, and (b) the matter that I missed, the “something very important” (which is not TK transfer).

p.s. “we know more than we can tell” is pretty much the tldr of T.D.


We can paraphrase "we know more than we can tell" in at least two ways:

1. "We know [the manner in which we carry out a task] more than we can tell [...but are unable to articulate the procedure by which we do it]." 2. "We [can do] more than we [can explain in writing or verbally]."

The second statement is uncontroversial. No one would say that the ability to ride a bicycle logically entails the ability to explain how we do those things in writing such that, by reading alone, someone could learn to ride a bicycle.

But this is only mysterious if you consider the second statement to be a paraphrase of the first. I don't think that it is. The first statement suggests a mystery; it's as if we are always following rules when we act skillfully, but are sometimes unable to articulate those rules.

But this is a mistaken view. Not all skillful performance is rule-governed. In fact, most isn't (statement two). And that is easy to forget, but does not require a theory of "tacit knowledge".

See also: https://plato.stanford.edu/entries/knowledge-how/


Possibly the issue is your conflating knowing with doing.

The straightforward parsing of that sentence for me is: We are not capable of completely expressing our (personal) knowledge with language.


We are in agreement. Doing should not be conflated with knowing, as the "tacit knowledge" approach tends to.


Good, we (the 3 of us) are in agreement. So what's your beef with brother Polayni?


I'm curious about the skepticism. Could you elaborate? The explanation of tacit knowledge hit me quite viscerally. I see a part of my engineering work as turning tacit knowledge into explicit knowledge.


If you haven't yet read it, go straight the source on this one and read Peter Naur's "Programming as Theory Building". The paper is excellent, and an easy read. It's linked to by TFA.

The consequences of the logic contained within Naur's essay are far stronger than I think the article understands them to be.


It's not exactly an easy read -- whenever I recommend it to someone I also warn them that it contains the most passive sentence in the history of the English language: "Information obtained by a member of group A about the compiler resulting from the further modification of it after about 10 years made it clear that at that later stage the original powerful structure was still visible, but made entirely ineffective by amorphous additions of many different kinds."

But the content more than makes up for the style!


Can someone help me understand why Twitter had not crumbled from the overwhelming weight of software decay after 50% of the staff was laid off? I’m not being sarcastic, it’s just honestly hard for me to understand…


People leaving doesn't cause decay. Decay happens over time - usually not just in a month.

People leaving means that there's nobody there who can fix the decay when it happens, though.


There's a number of plausible scenarios:

1. It takes more time for the rot to show.

2. Twitter devs were amazing at building really solid software

3. The culture of twitter was really that 1 person did the work and 9 others watched, enough of the productive devs stayed.

4. The effects of rot are overestimated.

I have no insight into how twitter worked as a company before Musk's takeover though, and I still think it is quite likely major problems will occur in the next couple of months.


Patience. It hasn't been long, and they probably left a test suite running under CI. Ideally it doesn't push to production without the tests passing and noone is left who knows how to disable it.


I mean, this test is really annoying and it's testing a case that I'll guarantee 100% won't happen often in production.


Did they ever disclose exact amount of engineers that were laid off? Twitter laid off lots of people but I doubt majority of them were engineers.


According to this: https://gizmodo.com/elon-musk-twitter-layoffs-engineering-sp... the first round of layoffs was around 40% engineers.


This is of course just my opinion, but I'm pretty sure what kills off a legacy project is whether the organization is committed to maintaining it rather than it being some kind of property of software itself.

Minimizing churn is just one aspect of that commitment. If the project was always a mess it probably wasn't as important to the business as the developers believed.


This is a poorly written article by someone clearly projecting their own individual experience (or more clearly, the lack thereof) onto a giant world of professional phenomena.

It is trivially easy to think of a structural counterexample to their primary point, which is how experienced senior engineers can inherit production codebases without documentation or the original team that wrote it and are able to successfully operate, understand and improve the entire codebase. Is there a gradient of pain? Yes. Is it possible to inherit a codebase that is falling apart, without the resources to get the ship back on track due to organizational issues? Absolutely.

However, it doesn't change the fact that every year, significant quantities of senior engineers do something that the author does not believe to be possible. This isn't to say employee churn is particularly health for software companies; it's often not. But that really varies on a case by case basis.


maybe but can an org afford to pay for those super seniors or is that not a valid option except for companies with deep pockets?


What is the bear case for this essay? It's notable that almost all large organizations operate in a diametrically opposed way, yet we have thousands of successful incredibly complex software systems. To me the essay feels intuitively true, but I'm not sure how to reconcile it with this empirical fact.


Of course, this often works the other way as well: a project is failing or stalled by the "wrong" theory being saturated through the team, and it can only be fixed by replacing individuals and developing new mental models of the problem.


Isn't it obvious? Senior or long-term employees that leave take with them tombs of process/folk-knowledge with them. They take the answers of "who do you talk to in what team to get x done?" and "how best do you navigate this team and their hot-headed manager to get what you need?" etc. etc.

Documentation is helpful but the intangibles that come and accrue to just someone or someones who have been in the trenches for years and years can't be documented and when they leave it can be fatal at least for a team/unit.

Add to that the onboarding cost and the cost of hiring: take in-house or (worse) external recruiters and their salaries/commissions, add to that senior engineers taking time to interview candidates and both prep for the interview (hopefully) and then write up detailed notes afterwards -- count not only their time doing this but their time NOT mentoring a junior engineer or working on something else during that day (yes this might sound like double counting but senior engineers really do make 1+1=3 so pulling them off something is extra costly imo), and then add the expense of the employee being hired, all their gear that they'll need, and then the 3-6 months until their productive and all the help/training they'll need to get to productivity AND THEN imagine all that and then person leaves after 6 months to a year: how much does that cost? now multiply that by your attrition rate... it gets hella costly.


Meir Lehman wrote [1] extensively about software lifecycles and evolution, and came up with what he called "laws". Most of them should be familiar to HN readers. To sum up as succinctly as I can: programs in use undergo continual change; as a program is changed, it becomes more complex; the quality of the system will degrade over time unless rigorously maintained.

He also wrote that over time a software system, through dynamics of the programming process, the rate of change tends towards being statistically invariant. This is because, he said, the team involved in the system, including not just the developers, but also the users and others, have a finite ability to maintain understanding of the system, and excessive and too-rapid change outpace the ability of the people to maintain understanding.

A Sixty North blog post[2] provides some interesting graphs showing the measured effects of Lehman's laws, including one showing that after 5 years, almost 2/3rds of the code is written by people who joined the team after the original team members left.

1 Metrics and Laws of Software Evolution - The Nineties View https://ieeexplore.ieee.org/document/637156

2 https://sixty-north.com/blog/predictive-models-of-developmen...


> What keeps the software alive are the programmers who have an accurate mental model (theory) of how it is built and works. That mental model can only be learned by having worked on the project while it grew or by working alongside somebody who did, who can help you absorb the theory. Replace enough of the programmers, and their mental models become disconnected from the reality of the code, and the code dies. That dead code can only be replaced by new code that has been ‘grown’ by the current programmers.

While it's possible that there are systems out there that can't be understood, it's plainly false that - to paraphrase - code dies and must be replaced when the original developers are gone.

A couple examples from my direct personal experience:

1. I work every day on code that's 20-30 years old, in use in production by hundreds of millions of people every day. There's no one around who worked on it originally. And yet it works, 100s of pull requests a day, and customers continue to pay us to use it.

2. I took on a volunteer project this fall, working on a ~million line distributed system that runs on clients at about 30 sites and integrates with 3 cloud services. No original developer is working on it. For the client code, it took me about a day to understand how it works and make meaningful changes.


For both of these cases, the article author would say that the original developers have been replaced by newer developers who have acquired the theory.

The solution to the problem, at least according to the article, isn't "no churn ever", but "low enough churn that the newer developers acquire an accurate mental model of the system."


The author starts with the implicit assumption that the companies in the target audience will not be able to restart the metaphorical engine, which is why they recommend letting it idle. They tactfully don't call attention to the fact that not everyone has that problem.


We're having an issue of employee churn, and I think a lot of that is 20+ years of tech debt is catching up and new developments are becoming extremely difficult.

I was just wondering if it would be good general practice to refractor piecemeal every couple of years. This would (in theory) reduce tech debt, and if the refactoring is done by relative newbies, you ensure the base is understood and stays fresh.

I haven't hashed out or thought this through yet, so happy to have holes poked in this idea


Totally agree - perhaps put more succinctly many rewrites are an attempt to independently rediscover the business requirements by reversing it out of code:

"Team stability is vital for software development. Each team needs to be composed of a majority of first-generation developers. Too many second-generation developers and the first generation gets overwhelmed, and work stalls. The work slows down either because too many core tasks are waiting on the first generation or because the second generation keeps having to rewrite components from scratch because they didn’t understand the theory behind the original component. Too few second-generation developers and there is no renewal—each developer that leaves the team is a potential catastrophe.

Many teams in the industry constantly rewrite parts of their code. Not because they keep figuring out better ways of approaching the problem but because nobody on the team has an accurate mental model for how it works and how the code fits in with the rest. If you can’t hold onto the original team, if you grow the team too quickly, you end up running to stay in place. Code keeps getting written without any improvements of substance to the software itself."


Honestly, I think all these layoffs hurt companies. Hiring is difficult and a slow process. Being unable to think of something profitable for devs to do inside your company is a sign that your management is being ineffective, or that ideas are being squashed inside your company.

I'm skeptical that these companies were so bloated that they needed to lose large percentages of their headcount.


This is the similar to the classic "design concept" from "the design of design." It is the idea that must be shared between the software developer's minds to increase velocity, not software itself.

The pressure you face in communicating this theory is time to market. I am obsessed with cleanroom, zero defect software, and literate programming. However, I have only worked on one project that these tools would have been relevant for. All others, the code/system moved on faster than the time it would take to get it communicated.

The real measure of programming languages to me then becomes raw productivity. If we could make programming literally a 10% or less task, and documenting and communicating the 90%+ task, I think software companies would do very well. This bodes well for things like ChatGPT/copilot.


Losing institutional knowledge kicks the org. in the proverbial balls. Even if stellar seniors come in to replace the ones who left, they still take 3-4 months to get up to speed on institutional knowledge, and they rarely can get all the knowledge that the ones who left had.


> What keeps the software alive are the programmers who have an accurate mental model (theory) of how it is built and works. That mental model can only be learned by having worked on the project while it grew or by working alongside somebody who did, who can help you absorb the theory.

That's the easiest way to learn it, but it's not the only way. After a while, it even becomes fun to read through other projects (some of your dependencies, e.g.) to see how easy it is to develop this 'theory' (even if it is fleeting; in the case of dependencies, you'll at least keep a rough idea of the cost of that dependency, relative to it's value)


I don't disagree, but which companies have died largely/entirely due to churn? Running out of money, getting outcompeted, etc. will all lead to churn but it seems that churn itself is more of a lagging indicator.


Seems related to the concept of conceptual integrity as stated by Fred Brooks: https://wiki.c2.com/?ConceptualIntegrity


The incentives are broken for software engineering companies.

Most of them are operated with a startup mentality, aka we will be around for 18 more months so let’s optimize for that.

All of the employee benefits are incentivizing them to stick for the short term and then move to other pastures.

Or you know they could instead offer high 401k, pensions, career options for people over 55y.o. etc.

But it is always easier to burn though fresh grad meat, and let the dumpster fire for someone else to deal with.


My company actively promotes rotating to different areas of the company every 18 months. I think it's terrible for continuity as well as skills development.


It's good to know how different areas of the company, but that's taking it to the extreme!


This is why I would recommend for low barrier of entry software, like web development, to only ever use the most opinionated frameworks available, but this isn’t desired from a hiring perspective because of web tech hype.

Hell, I would recommend Java over nodejs for this reason.

All jokes aside, time and time again have I seen web projects erode away with 1000s of employees taking a quick hack or asking for large refactors and then leaving soon after.


Employee churn has a very real cost and many executives are still struggling to understand this. I think many have just never seen it before or are in denial, but it guts an organization.

I have seen teams and divisions that operated like clock work suddenly descend into chaos after 25 percent of the team left for higher pay. Once that happens it is over. Everyone leaves because work becomes terrible for everyone left.


This is why the UNIX way, where every program does only one thing and does it well, is so powerful.

You don't need to know how it works to use it. And if it really needs changing you can make a new executable with a new version number in its name. That way legacy code can continue to call on the old still functioning version while other peaces of code call on the new version.


This is an excellent paper, it changed my view on programming. I've written a similar essay [1], summarizing the paper and providing some case studies as examples from real-life projects.

[1] https://hiringengineersbook.com/post/autonomy/


In my opinion, every piece of software should be entirely rewritten every 5 or so years, taking into account the previous iterations mistakes and successes.


It really doesn’t matter and it’s definitely not lethal.


After 200+ years of capitalism It's now deep rooted in our society that all work is a commodity, with human labour wholly fungible.

This in and of itself pretty dreadful but I have been wondering recentl whether or not abstract thought is quite so. I'm not quite sure.


Capitalism doesn’t treat people as fungible, but instead according to a power law according to their capitalist value. Rare valuable skills tend to get paid highly, with professionals in the middle somewhere. The most common skills get paid near a minimum set by regulations, and also minimum wage is set by competition - see https://en.m.wikipedia.org/wiki/Baumol%27s_cost_disease

High level capitalists (such as VCs) treat rare people unfungibly e.g. Paul Graham “the success of a startup is almost always a function of its founders” or http://paulgraham.com/founders.html

Edit: also fungibility is by no means a capitalist idea, and it is a central concept to some non-capitalist doctrines. What is equality?


Paul Graham the capitalist is not Paul Graham the coder. One uses his time to produce something another uses his capital to buy others time.

But also reducing to single entities misses the forest for the trees. Commodities and there exchange value is a social construct that naturally appears as we exchange goods and ultimately human labour time.

The high skilled worker's cost is not just the time now but all the time spent to get to that level of expertise.


Tell that to Elon or Bezos or the other geniuses of our lifetime




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

Search: