The mechanism I've attempted to use to show to non-programmers whether a feature is written in a supportable way and encourage team members to write supportable code is by listing out every feature row by row.
Then in each column a team member will sign up as the lead for the feature. The rest of the team members will have to rate (from green to red) whether they are willing to PR review the feature commit, be on pager/bugfix duty for that feature going forward and be on the hook to add new subfeatures to the original feature.
Team members who lead features that have many green checkboxes for their rows are highly visible to management.
Team members who add esoteric dependencies and add too much "job security" also quickly realize they are going to be the ones stuck debugging/QA'ing that portion of the code.
It also allows PMs to understand the level of bus factor/ redundancy for each specific features. Its quite possible some features are experimental and don't need redundant support.
In my opinion, it's people who have the need to abstract away everything who complicates the code bases.
Give me simple, elegant code that doesn't complicate what the program does, and you have maintainable code that can be changed and deleted easily.
Simple dumb code, unless absolutely needed to be "fast and smart", should be the defacto standard. Which is why Go is so good as an enterprise language. Its very design is a standard for maintainability.
So how many ways could you come up with that accesses data in a file? You have an OOP filemanager class which can handle CRUD to ISAM and RDBMS (SQL) back ends, the windows API's both to disk files and ODBC if the RDBMS doesnt have its own library. If you dont check and enforce basics like this, you will get eloquent functional code that meets the remit but doesnt fit into the app, eg some procedures which read and write to a file using win32 apis but ignores the OOP filemanager that exists and then the OOP filemanager class doesnt know what files are open on what thread.
The problem here is management didnt have any rule book for the basics, they also couldnt or didnt want to pay for someone else to look over the code to ensure standards/rules were being met. And then businesses wonder why their apps gets pwned so easily? Shareholders dont always learn because they dont fire the board who presided over such fubars either. And so the cycle repeats.
The main developer was an old mechanical engineer who learned coding by himself. And to be simple, his code was simple. There was a GUI with a 7x8 table of numbers. How to do this? 54 text fields, all with their own name with copy pasted initialization. Most variables were global, no class hierarchy, no fancy algorithms, juste nested loops, etc...
Because it was so straightforward, it was surprisingly easy to understand despite its complete disregard of any methodology. If it has to do A, you will see A, no surprise action at a distance, and if it has to do A ten times, you will see AAAAAAAAAA. But maintaining it is as bad as it may seem, and if you have to change A to B, you will need to change all ten of them, being careful that they may be slightly different, and forget about parallelism, security, undo, etc...
So yes, simple code is simple, but without at least some level of abstraction it will soon end up being terrible. What is too much or too little abstraction? Just hire a few world class developers and give them as much time as they need, because it may be the most difficult question a developer has to answer. In fact, one could argue that the mythical "10x developer" is one who answers right.
Sorry, I have to fix this : 56
I recall a self taught dev (or maybe from a bootcamp) coming up with a cascade of nested if-else, nested 8 deep. Someone with a background in CS asked him what he was trying to do and basically concluded that what he was trying to do could be expressed as a state machine. To which the initial dev replied that it was "way too fancy" and that he didn't need the code to be fancy, just work.
This way of telling may give impression you are inplying that CS graduates know patterns and self-taughts don't. You will certainly find self-taught who know Finite-state Machine very well, and CS graduates that might have heard but can't identify where to use nor how to implement.
Because if they’re wrong at least you know quickly, instead of them secretly making a mess for a long time before you figure it out.