- A working CI pipeline.
- Comprehensive tests.
- Enforced linting/formatting.
- A script (or at least documentation) to set up a dev env from scratch (including resetting it if it already exists).
- Documentation of things which would take days or weeks to discover when working without the original developers, such as high-level trade-offs, code style which is not enforceable using linting (such as "Use Foo.frobnicate rather than the built-in frobnicator because …") references to issue trackers, former non-committing project-related people such as business analysts, separate documentation, credentials etc.
That said, I keep getting more and more picky about what it means to have a good code base, so in a few years I'm sure this list will be woefully incomplete.
I have inherited a couple of 10 years+ codebases at my current place, I would say that usually the best ones have small functions that are well documented instead of crazy abstractions. They also were built without trying to be too clever.
They use the bare minimum of the language to get the job done and do one thing only and well.
Some other code bases are much harder to grasp .. usually abusing abstractions everywhere or using libraries / programming constructs that aren’t widespread.
One that I despise is a huge asynchronous Python application built years ago with twisted.. nothing feels pythonic and it’s so hard to follow the flow of the program.
I inherited overengineered ones a few times and it's terrible. There's the Chesterton's Fence to be careful of, where some thing seemed pointless but fenced off an obscure bug. The pre-Kotlin Android era also had a lot of hacks to reduce boilerplate, which ended up being a tradeoff between spending 1/3 of your time dealing with easily fixed dumb bugs from copypasted code, or spending 1/3 of your time dealing with complex bugs from testing issues, code that reduced boilerplate, old things that were deprecated in new APIs, and so on.
Customer supplied some code that I had to incorporate into a new JEE app (actually J2EE back then).
I liked that code because it was just way cleverer than anything I ever expected to find in an enterprise Java app. It implemented a trie to return a list of partial recordings to make a full sentence (which was the input).
It was space and time efficient, but also extremely clear, logical, and easy to incorporate into our code base.
And best of all I was able to use those ideas to solve a similar problem in the next project.
It was a relatively straightforward rails site written by a person who didn't break any norms. I knew right where everything was before I started. It was quite nice, and then I probably ruined it.
Twice no. One was a massive in-house project that had evolved over the years. There was a former developer, but he was not very good, and only wanted to add more bells and whistles. He got frustrated with my efforts to document the code and left. It was used to help test other code, but was the most horrid thing.
Second was 5 years ago, person left, and left literally no documentation. We had a weeks overlap, and he demonstrated the code, but in the thousands of lines of code there were a handful of comments that just had the date and his initials.
For me I need to be able to understand what the intent was of the code. Then I can either debug the indent (i.e. bad logical thinking), or implementation (not coded to do what you want).
Relational database schema is the bedrock foundation of a good codebase (for business apps especially)
“Who wrote this sh!t?!?” >git blame Oh, it was me... well I’m sure there’s a good explanation.