On Habré (and in real IT life) there are many questions like:
- Do I need to update the system (or dependencies in the application), if everything works?
- Do you need any tests (autotests) in the application (you will spend your time and money of the customer on them)?
- Does it make sense in patterns and the allocation of abstractions (after all, this smears the code, leads to poor performance, etc.)?
The key question in all the examples below is: what do you develop: a product or service? Oddly enough, but as soon as you answer this question about products and services, all doubts about the need for tests, abstractions, etc. will disappear by themselves.
Terms
There is a fundamental difference in them: the product is complete, you can sell it, and then forget about its existence. In the case of service, the buyer and seller communicate for a long time (by analogy with the subscription, which is the service itself).
Product examples:
- Construction of the bridge. Actually, the bridge was built, delivered (this is a fundamentally important step), the construction company has forgotten about it. In reality, there is still a guarantee for the construction, but for the sphericity of the experiment, it is better to pretend that it is absent (or very short). During construction, it will be absolutely illogical to change plans in the process (for example, to return the brought fence and buy another, more efficient).
- Sale stools. Everything is analogous to the bridge, the most important thing is to sell this very stool. After that, the seller will forget about the buyer for a very long time (at least in most cases).
- Sale of apartments (especially in the secondary market). Here again, the most important thing is to sell the apartment so that it does not fall apart in the first months. And what will happen next - the seller is absolutely unimportant.
Examples of services:
- Banking service. The client pays for the service once a month, the bank provides the service for the whole month. The client and the bank remember each other for at least the whole month, and often several years. It makes no sense to sell illiquid, because the client refuses to service rather quickly.
- Taxi service (ie Yandex Tax, Gett, etc.). Despite the fact that the trips are complete, companies make the main money on regular customers, on those that return. Therefore, there is no point in deceiving the buyer on the very first purchase (in the style of bombing), since the relationship here is long.
- Supermarket. Again, for us, the duration of the communication between the seller and the buyer is much more important than the immediate benefit. And this means that instead of selling spoiled bread, it is more profitable for the store to recycle the batch. Otherwise, the buyer will buy bread for the last time and will not come to the store at all. Moreover, unlike the bridge example, it’s absolutely normal for a supermarket to “refactor” - an analysis of how efficiently the racks are, etc.
Why do we need to know the difference between product and service?
The idea is simple: if you view your program as a commodity (that is, your connection with it is interrupted after the first release), then there is no point in wasting too much time on tests, or on refactoring, or on matching coding styles . After all, if you spend your time and make it "perfectly well", then your product simply increases the cost. And in the future, these abstractions will simply not be needed (after all, you will stop working on the program).
However, if you provide a service for users (for example, make an analogue of Facebook), then you will have tasks for updating dependencies, you will have tasks for adding / removing functions, and therefore there will be tests, because they will reduce risks in the long term. Moreover, you will need to allocate abstractions, at least in order to build new logic in the future. So, if you consider your development as a service, then you need to update dependencies, write tests, highlight abstractions and do a lot of other work to avoid legacy and minimize the risks of mistakes in the future.
Manual: how to make a legacy program with your own hands
In the context of this article, it is very easy to derive a formula for how it is very easy to make legacy from almost any developed software, and following this formula for success is achieved by the developer of this program itself, without anyone’s help. The formula is simple: to get legacy software, you need to treat the development of service software as if you were making a product .
Or in other words: if you see that you are participating in the development of the service (that is, you are in this project for a long time, you will add new functions to the project for several years, adapt it to new realities), but there is a desire to make the project a true legacy ( there is a program in which it is incredibly difficult to make changes, which is unable to work on a newer OS / hardware, etc.), then just start treating the project as a product. Just treat each release as the last. Use the words "well, everything, have sold the version." As actively as possible make small crutches and hacks, instead of processing the code. And finally: more manual labor (forget about TeamCity / Jenkins), and never write documentation, specifications and various comments in the code.
It is quite interesting that if you literally slightly change the attitude towards software, then it will itself become a terrible legacy, and moreover made with your own hands.
Manual: how not to make their programs legacy
Strangely enough, however, in order not to get terrible software on hand, you only need to ask yourself a question once a month / quarter: and the product that I make is a product or service? And remember / write down this answer at least for a while. In the future, any questions about tests, refactoring, documentation, etc. will disappear by themselves.
Examples:
- What should we do with tests that constantly drop with each update of dependencies and with each release? And they fall not in the case.
- For the commodity program: it is better to simply remove these problem tests. Anyway, they now have more problems than good. And in the future they will not need anyone.
- For a service program: it makes sense to repair / fix tests in order to reduce their false-positive triggering. Each repair test - this is our time, but the presence of these same tests will reduce the risk of missing an error in the future.
- Should I upgrade to Spring Boot 2 , or does it make sense to stay at 1.5?
- For the program-product: strictly not. We will finish the project soon and will never return to this customer. We will have no tasks either to support this program, nor to add new features, nor to update to a new Java with security fixes.
- For the service program: strictly yes. After all, this version will be unsupported in a year . Moreover, in order to run on free Java, we will need to upgrade to Java 11 very soon, however, a number of modules from Spring Boot 1. * (at least ASM) do not support bytecode from Java 9+.
- Should we update the technical documentation for the product?
- For the commodity program: are we paid for it? If not, it is better to remove it altogether, since there may be errors in it, which then have to be corrected "under warranty." And if there is no documentation, then there are no errors.
- For the service program: of course yes. After a couple of years, this documentation will be very useful to us when new developers have to explain how and why everything works so well for us.
Product or service sells IT outsourcer
Despite the fact that an outsourcer is technically an IT company (moreover, the main part of the record is people related to IT), the most important steps in the project:
- Signed a contract with the customer
- The customer has signed the "acceptance certificate" (or in another way - the finished product is sold)
That is, all other actions of the company's employees revolve only around these points. And it is precisely these two things that directly affect what the outsourcer himself develops - a product or service.
For example, goods are often developed for government orders. And never the services (although this also happens). Therefore, in such projects there is no reason to do the documentation, speed up the work of the program (that is, make the customer satisfied). So we get the rule: if you develop, test or customize software in an outsourcer company that forgets about a contract after signing an act, then there is no point in even thinking about tests, documentation, highlighting abstractions, etc. Moreover, if you advise the middle manager to "make software better", he absolutely will not understand why you are thinking about this in principle. After all, a company is not only not getting any profit from refactorings, it can often suffer real losses from the fact that a developer spends time, do not understand what.
Moreover, if an outsourcing company makes such software to order, then it often has no incentive to make the programs safe (after all, in the future you can always just run over a blogger , as they did in the 90s, right? But the customer will suffer all the losses )
So why do you get legacy?
After reading the article, the thought involuntarily is born: after all, all these ideas are painfully simple. Why then do we get legacy software? Why does one company / team have products that are easy to support, while others have programs that slow down and developers spend a lot of time on support?
One (of many) answers is the attitude of the people themselves in the teams to the programs as a product or as a service. And here it is important to understand that in this context, the team is all people who were related to the development of software, that is, testers, and developers, and analysts, and management. The total position of all people and gives the position of the team. And it can be like “we sell goods”, and “we do service”.
Examples of conflict when a team develops a service, however, treat it as a product:
- If the project participants are not interested in long work with this project. For example, a person may plan to leave the firm in the near future. Or the company has a high turnover (including when people often move from team to team), which leads to the fact that project participants may not associate themselves with this project. Those. If you know that in six months you will work with other people and on other tasks, then what's the point of investing strength in the current program? Why write documentation, why do auto tests, etc.? It is better to just do it quickly, get an award for the accelerated five-year plan and go to work in another place.
- The method of carrot and stick in a team / company is designed so that it is much more profitable to report more often on the creation of new products and on the replacement of old ones. This can happen if all the bonuses in the company are issued for the fact that "product A was made" or for the fact that "product B was redone" and not for the fact that "product C is constantly evolving and helps to make money." In this case, all reasonable people will avoid long terms (for this they will not give gingerbread). The key difference is that in the presentation, finished verb forms will prevail with respect to projects (ie, the program is completed , the project is completed ), instead of long-term ones (the service allows you to earn money, the team provides the infrastructure).
- And do not forget about the standard sabotage (or job security ) - why do the documentation for the product that you know well? After all, otherwise the manager will easily find you a replacement. Why simplify life with software support? After all, if software support is very simple, then you can be replaced by someone else. This item is very intersected with the first, which described the company with a high turnover. However, it should be understood that the conditional "job security" has little in common with the idea of goods or services, it just is often a good explanation of many processes, so it is impossible not to mention.
Examples of reverse conflict when a team actually creates a product, however, it treats it as a service:
- Misunderstanding of business. Even a very honest outsourcer rarely admits that his profit is the difference between how much a customer pays for a project and how much he can cost in a minimal performance, provided that the customer is ready to accept it. That is, the basic salary is an opportunity to save where it would be unwise to save in the long run. This is where a conflict arises - if the middle manager tells the customer that "we are doing the best software in the world", then the developer can begin to take all of this at face value.
- Always did. If the enterprise java developers team (doing services that are then improved and supplemented over the course of a decade) are given the task of "making a temporary service for copying files from point A to point B", then there is a great chance that this simple service will be over complicated. Yes, it will copy the files, but the copy itself will be hidden behind 10 layers of abstraction (and after a couple of months - for the 11th ).
The impact of products and services on languages and technology
On Habré there is often a lot of controversy over which programming language is better. Or which technology is better. Strangely enough, many of them arise from the fact that the parties have a different understanding of what a program is - a product or service.
If you have a one-time task (for example, copy files from point A to point B with some conditions and minimal conversions), then it would be rather foolish to choose technologies designed for long support, giving long backward compatibility. For such tasks, Go / Python would be the perfect solution.
And vice versa - if your task includes a long-term service (with frequent security updates, etc.), then such advantages of the platform as backward compatibility, ease of updating, ease of patching, etc. come to the fore. It becomes absolutely unimportant to you whether it is easy or difficult to write Hello World in your chosen language, since such programs will be created every few years.
And how to use it?
In conclusion, how to use the fact that the program can be both a product and a service.
- Once a month, just remember what you are doing: a product or service.
- Do not try to develop the product. It is sold once and forgotten. This approach is incredibly clear to business. Work on the system "made - forgot."
- Do not treat service projects as goods. You will communicate with users for a long time, in this case it is more important for them to have long-term cooperation, and not momentary benefits.