Note that requirements change, and bad tests will break on no requirements. Telling the difference is an exercise for the reader.
1. Ask for forgiveness and do whatever you think is prudent regardless of org structure.
2. Find a better org structure elsewhere :)
The tests tell you what it's supposed to do, not how it does it.
They are when devs put all the code into those header files.
> 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.
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.
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.
> 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.
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.
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.
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.
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.
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.
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.
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".
Code documentation, in contrast, should be auto-generated from the code.
But yeah, totally into auto-generated (great example is dbt’s docs command: https://docs.getdbt.com/docs/collaborate/documentation)
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.
That's the thing about places like that.
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 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.)
that describes pretty much every tech company in the past 18 months ;)
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.
I ask about ‘points’ in interviews, its an immediate stoppage for me
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.
- 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.
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.
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.
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.
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.
+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.
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.
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.
Unless you're a mega corp - you're not getting a good work management solution.
/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.
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.
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.
Don't fight management, leave.
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.
> 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.
> 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.
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.
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...)
Most people do not have the memory span to work with mutable state, so something simpler should be the default.
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 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).
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.
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 are 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 a bit like tech debt, just documentation debt.
While writing good documentation isn’t easy, the fact that it usually gets neglected is a cultural issue.
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.
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.
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?
Write your RFCs as markdown in a git repository. Stick it to the man!
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.
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 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.
Although the example uses Python, rather than shell.
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.
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.
- 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.
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.
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.
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.