How to live and develop on projects with history. What gives the developer the experience of working with a large code base, and why there is no need to strive to rewrite everything from scratch, even if you really want to.
Content
- Who is this text for
- What you can learn from a story project
- What questions to ask in an interview
- Tips for those who have just started working with a legacy project
- Briefly
I am Pavel Novikov, I am involved in the development of mobile applications "MyOffice Documents" and "MyOffice Mail". This is an application for collaboration with documents and an email client, which began to be created in 2013, so they can be called projects with a large codebase, where there is a place including legacy.
The experience described here applies not only to working on mobile applications and scales to application development in general.
Disclaimer for the little ones
In this article, I have collected reflections on my work based on the experience I have to date. Any articles of this kind are always highly subjective. I'm sure there are people with experiences that contradict my observations. I would be happy to discuss these discrepancies in the comments.
Who is this text for
The text is intended both for those who consider themselves to the Junior level and for those who fall into the Middle / Senior category.
There is a lot to learn from working with long-lived projects at any level of development. To be on the same wavelength in understanding the levels, read the posts of Vastrika: Login and K - Team . I like his categorization of developer tiers, and I'll stick to it in the future.
In the next block, we will briefly analyze what is the use for each of the levels on long projects.
Junior
The task of Junior developers is to maximize the development of technical skills. Everything is used: languages, frameworks, libraries, development approaches, etc. On any project with a strong team, you can learn to solve different problems.
But on mature projects, firstly, you will have the opportunity to dive deeper into any area and, secondly, you will be able to study examples of successful and unsuccessful decisions. Learning from the mistakes of others is expensive. Especially if there are more experienced colleagues nearby who can explain to you in detail the meaning of these mistakes and how they can be avoided.
Middle
The Middle Developer's task is to increase its autonomy. You should become a team member who can be trusted with almost any task on the project. This means that the more varied tasks a project has, the more potential growth areas you have.
Senior
The Senior Developer's job is to fully understand that you are not paid for the code, but for solving problems. Sometimes (still more often so far) through writing code, sometimes through managing other developers, sometimes through communicating with non-developers. Mature projects are just a storehouse of tasks that can and should be solved.
Next, I'll go into more detail on some of the things you can learn from existing projects.
And here Legacy?
First you need to understand the terminology. The concept of "legacy" has acquired a negative connotation long ago, but what exactly is the legacy code bad for?
Michael Feathers, founder of R7K Research & Conveyance, argues that legacy code is code not covered by tests. The advantage of this approach is that, at first glance, it claims to be objective. But in reality, there can be two scenarios:
- There are tests, but they are poorly written: confusing, fragile, not obviously structured.
- No benchmarks, but the code is very well designed. This makes it possible to change it relatively safely and, in which case it will allow you to quickly write tests for it in the future.
Another look at what legacy is from developer Dror Helper: No longer engineered - continuedly patched and hacked. ...
Web developer Nicolas Carlo believes that legacy code is uncomfortable code to work with.
From all this, we can conclude that legacy is rather a subjective characteristic of the code. The code itself may or may not work, but it will become legacy when a developer appears who cannot effectively modify it.
Another relatively objective characteristic for evaluating Legacy is the answer to the question "are there any unsupported dependencies in the project." The code can only be built by some specific obsolete compiler versions. Or the authors themselves patched some external library, and it has now become part of the main project. In this case, indeed, the project becomes specific, and additional efforts are needed to support it.
In general, if the project is more than six months old, then most likely it will contain legacy.
What can you learn from a story project?
So, you made a decision and got a job in a company where code was already written before you and a lot of other things were happening. I will add that you do not need to go to a new place in order to upgrade your profiles. Legacy is most likely in every project, you just need to know how to evaluate it. And what I'm talking about can certainly be applied to the things that you are working on now.
In what areas will pumping be equally useful for you and the project? Here you need to understand that the situation when you develop where the project hurts is an ideal environment for mutual growth. Because if you develop in working on some leftist things, then this may be a plus for you personally, but at the same time it will be difficult to explain why the company should help you with this.
Analyze the project
The first thing you can learn from a heritage project is to analyze it. Let's say you came to a project where there are gaps with documentation, or there is none at all. In this case, you will only have the source code of the project, so it is critical to be able to analyze it and quickly understand its structure and essence. This is important because the sooner you learn to navigate it, the sooner you will begin to benefit the project.
The most important thing I can recommend for a deeper understanding of the project analysis is to read the book "Effective work with legacy code" by Michael Feathers. She is old and famous. It describes a large number of practices for working with legacy code.
Another tip is to visit the Understand Legacy Code website.... This is a blog dedicated to one topic - working with legacy. It is important that you can subscribe to the newsletter there. I'm sure many Android developers know about Android Weekly and Kotlin Weekly mailings. The ULC newsletter is also very helpful. It is not intrusive, with how-to articles on refactoring and coding.
Refactor
Legacy projects are a great place to practice your refactoring skills. You come to a project that most likely has problems, and you need to not only change it, but also improve, expand and saw new features. How well and efficiently you can refactor (quickly and with few regressions) will determine how useful and good a developer you are.
In a mature project with a healthy engineering culture, refactoring should be an ongoing part of development.
You should like the product you are working on. Perfect if you can use it yourself. In this case, you will have internal motivation to work on improving its quality for a long time.
Design and create architecture
This point follows from the previous one - you will inevitably need to pump in software design and architecture. With the right development culture, you won't have to make major architectural decisions on tight deadlines. You will have time to design the architecture and it will be your responsibility to do it well. What do I always recommend here? Read books.
I find books to be just as important as other sources of information. The more experience you gain from books, the more and faster you will understand how to solve common problems. There are always typical solutions to typical / typical problems that can be found in books. Working with any kind of legacy also involves solving typical problems.
(Robert C Martin). « », « »
(Martin Fowler). «. »
UML — .
PlantUML (PUML) — , UML-. git, , .
When you work with a product that you don't fully understand, you will somehow need to learn how to evaluate the work to be done. And you will always have something that you do not know, some pitfalls.
The ability to break down a large, complex task into a set of small, interconnected pieces is a very valuable skill. One way to develop it is to continually retrospectively work on decomposition and estimation errors. In the process of analysis, you can create a checklist from frequently encountered errors. In the future, he will be able to help you prevent these mistakes again.
Automate and be able to apply CI / CD
You need to understand what happens to your code from the moment you write it to the moment it reaches the user's device. And you will have the ability to automate and CI / CD to customize, maintain, and improve. In companies where there is no dedicated infrastructure team, these operations can and should (I am convinced of this) be decided by members of the core development team. Modern tools (cloud CI, Docker) are not incredibly complex, but they greatly simplify the life of a team. You will be able to do her a lot if you master these skills.
To communicate
The more responsibility you have, the more people you will have to communicate with. Software development has long ceased to be the lot of individuals: almost all large projects are done by teams. Again, the more effectively you learn to interact with those around you, the more benefit you can bring.
You will have to communicate with people who are smarter and more experienced than you. In large projects, there are always “old-timers” from whom you can learn a lot. Also, you will meet people who are dumber than you. The good news is that you are most likely wrong about your mental ability - it is very useful to be able to correct such errors of perception.
I believe that developing communication skills can be reduced to developing a sense of empathy. The better you learn to understand the motivations and goals of the people around you, the faster you can become useful to them. For example, when explaining to a business the benefits of refactoring and working on technical debt, you should use business terms, not programmer terms. Seemingly obvious idea, but I have repeatedly seen how some smart people communicate with other smart people and cannot understand each other.
What questions to ask in an interview
Here I will build on what questions I would ask before going to work on a project that I know little about.
How the workflow works and why exactly
Usually now they work on Scrum or Kanban systems. But at the same time they often adapt them for themselves: "they took the best, threw out the unnecessary." The question is: what exactly did they throw out and what did they leave? Because the Scrum guide, on the basis of which the development process is built, has some pretty interesting and useful practices.
They make sense when applied, firstly, consciously, and secondly, all are applied. Because they make up a system that controls itself and allows you to iteratively improve not only the project, but also your own processes.
For example, if the team is working on Scrum, I would ask what was discussed in the last retrospective. How active is the team at this meeting? Are the issues raised being addressed?
Another interesting question for me on internal processes: how is code review carried out in the team? Are there any internal rules for conducting a review that can help reduce its time? Is there a common knowledge base in which the results of holivars are entered, so as not to suit them every time?
How planning works, who is involved and how active the team is
I would ask this question to see how strong the engineering culture is within the team. There is an option when only the team leader is planning, and the team is on his side.
Another option is when the entire team participates in planning. And when a task comes, it is undertaken to paint it by someone who has enough expertise in this matter. And then they all discuss and make a decision. This makes the team more self-organized and the workflow more enjoyable.
How many people in the team have the whole picture
Two extremes are possible here. The first extreme is when you come to a team that has been working on a product for the last 2-4 years. If at the same time the team did not change much, but only expanded, then this is very good, because you will always have people to whom you can turn for help. They will be able to suggest something, explain the reason, tell you the history of the project. Knowing the context and why everything is arranged this way and not otherwise is very important.
The second extreme is when you come to a team that does not have any of those who were at the start. For example, the project was frozen, it was unfrozen, and a large codebase remained. You cannot rewrite from scratch. Accordingly, it is necessary to restore the development. That is, you get a project in which you will need to dig everything up again.
Based on this information, you will be able to make a more informed decision about whether you want to go there or not, and maybe overestimate some of your requirements for the proposals that you need to answer.
How is the technical debt backlog maintained
There are problems in any project, and it is important to understand how the team works with them. I wrote very well about working with technical debtalexanderlebedevin the article “Lannisters Always Pay Their Debts! (and technical too) " .
If the team knows about the problems, but do not know how to work with them in a systematic way, then this is a bad sign. But you can look at this and as an opportunity to become the person who will help solve these problems.
Tips for those who have just started working with a legacy project
Resist the temptation to rush to rewrite everything from scratch
A common situation: you start working on an existing application and see that everything is done "wrong". And with this "not so" you need to work further. It is quite natural desire in this case - to take and rewrite it all over again. This is a normal reaction.
I think that it is based on unwillingness to answer for other people's mistakes. After all, if after your modifications new defects appear, then you will have to figure it out. It’s better then to rewrite it completely, and everything will be fine.
If you notice that you are having such thoughts, ask yourself a few questions:
Are there definitely enough problems in the code, or you just do not understand it yet?
Are you sure you understand exactly all the integration points of the rewritten code?
Do you know the project well enough to correctly predict the upcoming time for work?
While I'm convinced that the intention to immediately rush to rewrite everything from scratch is a bad idea. Improvements should be iterative and manageable.
Once I witnessed when the team said that “It's all bullshit, let's rewrite”, rewrote for six months and did not rewrite. As a result, a rather interesting situation developed when the project had to be lead from scratch again, to recruit a new team, because the old team fell off. Try to extinguish this completely natural urge to redo everything from scratch.
Predict project changes
You need to learn to be a little bit of an oracle. Working with a project for a long time, you will learn to understand its product component, learn to understand the business, how this project earns, how it lives. This will provide an opportunity to assess the long-term perspective of the decisions that you make.
This is a very useful skill, because it is a bad situation when the product owner comes to you and asks you to do something simple from his point of view. For example, add a new criterion to sort the list. And on your part, this will mean that you need to rewrite this entire component. This would not have happened if you had thought in advance that different ways of sorting that list is a perfectly logical function. Although she was not asked to do in the first place.
Just do not go to extremes and try to always make the most universal decisions. This is a direct path to time-stretching and problems with further support for such solutions. The whole point of this skill is precisely to find balance.
Do research
When you're working on a long project, how much the business trusts the team is important. Before developing any major feature, we definitely conduct a full-fledged research of the subject area. It may sound like a captain's captaincy, but I know of cases where people immediately rushed into the maelstrom with their heads, and seemingly simple tasks turned into lengthy refactorings that could have been avoided simply by doing research before development.
Take time to document
Document what you negotiate, document processes, document architecture. Here I try to adhere to the approach that if they did not write it down, then they did not agree. Because in projects that take more than half a year, it becomes critical to learn not to lose information.
When you make an architectural decision, it seems obvious to you. Why explain it somehow? Six months or a year later, problems arise in this architectural solution. And you think: “Why did I accept it? What was the context? " Learning how to write these architectural decisions is a great investment and will play into your hands in the future.
One of the ways to maintain such records is Architecture Decision Records... Its main idea is that for each non-trivial architectural solution, you need to create a file with several elements: title, date, context, solution description, expected consequences. This file is stored with the code and does not change after it is created. Its main value is that when the time comes to change this architectural solution, it will be much easier to understand the motivation that led to it.
Briefly
- A project with a history is a good place for a developer to grow if he becomes interested not only in writing code, but also in tasks that will help develop not only as a programmer.
- In projects with a background, it is not the code that creates the problem, but the people, that is, such management when they demand from you something very fast and constantly like in game development, for example.
- . , , , .
GDG.