Translated article Seven Deadly Sins of a Software Project by Yegor Bugayenko .Maintenance is the
most valuable advantage of modern software development.
Accompanying can be measured mainly by the working time it takes for a new developer to get into the project before he starts making significant changes. The more time it takes, the less the level of maintainability. In some projects, this time is close to infinity, which means these projects are almost not followed. I want to tell you about the seven deadly
sins that make a software product unaccompanied.
Anti-patterns

Unfortunately, the programming languages ​​we use are too
flexible . They allow too much and prohibit too little. For example, Java will not prevent you from placing the code of the entire application in the same class with a couple of hundred methods. Technically, the application will compile and run. But it is a well-known anti-pattern
Divine object .
')
Thus, an
anti-pattern is a technically feasible way to design an application so that it is deliberately wrong. In each programming language there is a fairly large number of anti-patterns. Their presence in your project is similar to a tumor in a living organism. Once she began to grow and she was already very difficult to stop. In the end, the living organism perishes. In the end, your project becomes unaccompanied and needs to be rewritten.
Once you have made a couple of anti-patterns, and their number, like a tumor, will only grow.
This is especially true for object-oriented languages ​​(Java, C ++, Ruby, Python), mainly because they inherited a lot of things from procedural languages ​​(C, Fortran, COBOL). That is why OOP developers tend to think in a procedural and imperative style. Unfortunately.
By the way, in addition to the existing
list of well-known anti-patterns , I would like to add
these few moments from myself , which I consider to be bad approaches to development.
My practical advice here is to read and learn. Perhaps
these books will help you. Always be skeptical about the quality of your code and do not relax when it “just works.” As in the case of
cancer , the sooner you diagnose it, the higher the chance of survival.
Untracked Changes

When I look at the commit history, I should be able to tell about each change:
what was changed,
who made these changes, and
why these changes were made. Moreover, the time it takes to answer these three questions should be measured in seconds. In most projects this is not. Here are some practical recommendations:
Always use tickets . It doesn't matter how small a project or team is, even if you are alone, create tickets (GitHub Issues) for each problem you have to solve. Briefly describe the problem in the ticket. Use the ticketing system for intermediate thoughts, so that later it would be clear what “those few commits” were for.
Link tickets and commits to each other . Of course, every commit should be accompanied by a message. No message commits is a dirty practice, and I won’t even discuss why. But the message alone is not enough. Each message must begin with the ticket number you are working with. GitHub (I'm sure you are using it) will automatically link tickets and commits, allowing you to
better track changes.
Do not delete anything . Git allows us to do "push --force", which overwrites the whole branch that previously existed on the server. This is just one example of how you can destroy development history. Often I have seen people delete their comments on GitHub discussions so that their tickets look more “clean”. This is simply wrong. Never delete anything; Leave your story, no matter how bad it is (or ugly) in your opinion.
Difficult releases

Each piece of software must be packaged before it is delivered to the end user. If it is a Java library, it should be packaged in a * .jar file and released on some repository; If it is a web application, then it should be deployed on some platform, etc. It doesn't matter how big or small a project is, there should always be standard procedures that test (test), package (package), and deploy (deploy).
The ideal solution would be to automate these procedures to such a level that they can be started with a single line command:
./release.sh
or
mvn deploy
Most projects are far from that. Their release process always involves a bit of magic, where the employee responsible for it (also known as DevOp) has to click through some buttons here and here, log in somewhere, check some metrics, etc. Such a
complex release process is still quite typical of the entire software development industry.
I can give only one practical advice: Automate it. I use
rultor.com for this, but you can use any tools you like. It is important here that the whole procedure is fully automated and can be performed using the command line.
Voluntary static analysis
Static analysis is what
makes our code
look better and therefore
works better. But this happens only when the whole team forcibly (!) Follows the rules dictated by the static analyzer. I wrote about this in
Strict Control of Java Code Quality . I use
qulice.com for projects in Java and
rubocop for projects in Ruby, but beyond that, there are many options for each language.
You can use any analyzer, but make it a must! In many projects where static analyzers are involved, the developers write beautiful reports and continue to write code as before. Such a “voluntary” approach does not provide any benefit to the project. Moreover, it creates the illusion of quality.
I say that static code analysis should be a mandatory step of your production pipeline. Assembly should not take place if any static analyzer indicated a violation of the rules.
Unknown test coverage

Simply put,
test coverage is the percentage of code that is tested by unit or integration tests. The higher the coverage percentage, the more code is run during testing. Of course, the greater the percentage of coverage, the better.
However, many developers simply do not know the percentage of test coverage. They do not measure this metric. They may have tests, but no one knows how deeply they penetrate the code and how much of the code is not covered by tests at all. This situation is much worse than the low percentage of coverage that can be measured.
A high percentage of coverage is not a guarantee of high quality. It is obvious. But an unknown percentage of coverage is a clear indication of maintenance problems. When a new developer joins the project, he should be able to make some changes and see how the tests react to it. Ideally, the percentage of test coverage should be measured in the same way as in the case of static analysis, the assembly should not take place if the value falls below a predetermined threshold (usually about 80 percent).
Infinite development

By “endless” I mean developing without stages (maystones) and releases. No matter what software you write, you must periodically assign versions and make releases. A project without a clear release history is an unaccompanied mess.
To a large extent, maintainability is when I can understand you by reading your code.
When I look at the source code and the history of its committees and releases, I have to see what the author’s intentions were, what happened with the project a year ago, where he goes now, what his development plan is, etc. All this information should be in the source code and, most importantly, in Git history.
Git tags and GitHub release notes are two powerful tools that provide me with all the information. Use them to the fullest. Just do not forget that every binary version of the product should be available for immediate download. I want to be able to download version 0.1.3 and test it right now, even if the product is now in version 3.4.
Undocumented Interfaces

Each piece of software product has its own interface through which it should be used. If this is a Ruby gem, then there must be classes and methods that I want to use as an end user. If it is a web application, then there should be web pages that the end user will see and use. Each software product has interfaces, and they must be carefully documented.
As with all of the above, this also applies to maintainability. As a new programmer on the project, I will immediately begin to study its interfaces. I have to understand what he is doing and try to use it myself.
I am talking here about documentation for users, not developers. In theory, I'm against the documentation inside the software. In this, I fully support
Agile Manifesto - a working software product is much more important than detailed documentation. But this does not apply to "external" documentation, which is intended for end users, and not for developers.
So, the interaction of end users with your software product should be clearly documented.
If your product is a library, then its end user is the programmer who will use it — not to develop it, but to use it as a “black box”.
These are the criteria that are used to evaluate open source projects in our
award competition .