Lannisters always pay their debts. What is the Lannister motto? Yuri Boldyrev smears petty sub-Kremlin blogger Rogers

Technological debt management practices in a single team


About a year ago, our team moved from a phase of rapid feature growth to a more fluid development with a focus on improving quality. At this point, our products have accumulated a noticeable amount of suboptimal solutions, ugly code, and outdated libraries. Something had to be done about all this.


To date, we have managed to build a process that makes the fight against technical debt predictable, painless and inevitable.


What we got as a result:

  • The team is happy. The release retrospective regularly includes positive points about improving technology and reducing technical debt.
  • For several quarterly releases in a row, we were able to increase functionality without increasing the number of lines of code in the project. Removing unnecessary code and simplifying what was needed reduced the size of the code base for existing functionality. And this reduction roughly coincided in scale with the new code implementing the new functionality.
  • During refactorings and upgrades, the product is always in working order. Every two weeks we release a fully working interim release.

Let me tell you how we achieved this.

What is technical debt

My working definition of technical debt is the amount of work that needs to be done to make a project meet the team's vision of what is great. Note that technical debt can arise not only due to the liberal use of crutches in development, but also due to changing ideas about beauty. For example, common industry practices have changed. Or developers fell out of love with OOP and fell in love with functional programming. Or the once fashionable framework is no longer a cake and it has become difficult to find specialists who would like to write on it.


However, the main cause of technical debt is entropy in all its diversity. Disabled unit tests, outdated comments that lost touch with the code, unsuccessful architectural decisions, implementation of features that no one uses anymore, a foundation for a future that has not come, and much, much more.


It follows that the appearance of technical debt is inevitable in any long-lived project.

When technical debt is not a problem

Why is technical debt bad? It increases the cost of further development due to a number of factors:

  • The speed of implementing new functionality is reduced.
  • The likelihood of regressions when correcting defects increases.
  • The development process becomes less predictable and therefore less manageable.
  • The process of introducing a new developer into the project is lengthening.

This loss is sometimes called "interest on technical debt"


There are situations where these losses are cheaper than eliminating technical debt:

  • The end of the project's life is near. Note, this is not the end of adding functionality, but the moment when you can stop wasting programmer efforts on support too. This category also includes one-off prototypes, one-off demos for exhibitions, etc.
  • The value of development time now is much higher than expected in the future. Urgent fixes to a fixed deadline, startups that are running out of money from the next round of funding, etc. In such cases, fixing technical debt can be delayed until the heat of the moment has cooled. There are projects that do not get out of a state of emergency, but the advice from this article will still not help them.

What to do with technical debt? Failed approaches

Approach No. 1. “We don’t have time, the release must be submitted yesterday”

The desire to meet tomorrow's deadline at any cost, to the detriment of development speed the day after tomorrow.


Sometimes a prefabricated structure made from crutches is an objectively correct choice. In my practice, this was most clearly expressed when making demo versions for exhibitions. The date of the event is strictly fixed; if you didn’t make it in time for an important exhibition, the next attempt will be in a year. In this case, you can display the product “out of your hands”, carefully avoiding all bugs. As an engineer, it’s unpleasant for me to do such projects, but the crutches in them are justified.


When you make a product that will last a long time, everything is different. Meeting the deadline due to dubious technical solutions is an expensive pleasure. The total cost is:

  1. from the implementation of the crutch itself,
  2. from its subsequent replacement with a full-fledged solution,
  3. from the suffering of having a crutch in between the previous points.

The second point is very easy to underestimate, and there is a risk of not thinking about the third, the most expensive one at all.


When you meet a tech lead with a twitching eye at a conference, it may turn out that it was the nightmare of endlessly debugging a design made from crutches that brought him to this state.


Approach No. 2. “Yes, here we need to throw everything out and write it again”

The worse the technical debt situation, the stronger the temptation to bury the entire project code and write everything again. This is one of the classic mistakes that can kill the entire project.


The topic is so well covered in the famous article by Joel Spolsky that I see no point in presenting my own arguments.

Approach No. 3. “We’ll refactor at night and on weekends so that the manager doesn’t find out.”

Arguing the need to eliminate technical debt in terms of business benefits is not always easy. The development team may be tempted to go around the rough edges and start a major refactoring on the spot. This can be done during non-working hours, in pauses between other tasks, or “on the tail” of other tasks by inflating estimates.


What's bad about it? Oh, a whole bunch of things:

  • Reduced transparency undermines trust between management and the team. Often subsequent attempts to correct the situation by imposing discipline and tightening the screws will lead to a further deterioration in teamwork.
  • An entrenched situation in which the priorities of the team and management are conflicting causes demotivation on both sides.
  • The fruits of refactoring are included in the product in unpredictable ways and cause regression bugs where they are not expected. In conscious teams, this leads to a sudden and unplanned load on QA. In the unconscious, it goes into production and breaks down there.

After the team uses this recipe, management’s eyes begin to twitch.

Our principles

1. Add technical tasks to the general backlog

There are a number of patterns in the life of tasks in projects:

  • A task that is not in the backlog has less chance of getting into work.
  • A task without a clear formulation has less chance of getting into the work.
  • A task that cannot be estimated with a high degree of confidence has less chance of getting into the work.
  • A large task will wait longer in the queue than a small one.

Maxim Dorofeev talks about these things very well in his “Empty Inbox Technique”


To prevent technical debt from accumulating, work to eliminate it should be completed taking into account the principles listed above.


All tasks, except the smallest ones, are listed in the backlog. This way they have a chance to be done not only in their free time, but also as part of the planned work. In addition, such tasks are more difficult to completely lose sight of - the backlog is looked at more often and more closely than at TODOs in the code, pieces of paper on the monitor, abandoned wiki pages, tea-stained napkins with diagrams and other sources of information.

  • If there is a non-trivial TODO in the code, it contains a link to the task in the backlog. We check compliance with this principle at code review and do not accept complex TODOs without references.

    There may be drama behind the comment.

    Once, next to such a TODO it was written: “Crutch. Product Owner made me do it. Remove as soon as possible."

  • When a developer realizes that some place requires refactoring, he creates an issue in the backlog.
  • When a developer has a desire to improve the platform, he creates a task in the backlog.
  • Long-term architectural plans are put into the backlog in the form of separate tasks as soon as there is enough certainty about at least the first steps.

As long as such changes remain inexpensive in terms of development costs and the amount of testing required, we can gradually improve our code base without interrupting business objectives or introducing additional risks.

2. Plan technical stories based on business priorities

If a tree fell in the forest, but no one heard it, was there a sound? If there is bad code in a project, but that module will never need to be changed, is there technical debt?


I believe that when a programmer finds it unpleasant to look at some old module, this in itself is not a very big problem. Much worse is what happens when you need to add new functionality to this module or expand the old one. Compared to making changes to well-written code, such tasks are more likely (and more likely to exceed the original estimate) and contain more bugs. Sometimes much more. To protect ourselves from these types of problems, we try to schedule refactorings so that they are done before writing new functionality in the same place.


If functionality changes and refactorings seem small, they can be done together. The empirically selected size of the task for which this approach will be optimal is 3 days of work for one developer or less. When it is clear that there is more work, it is divided into refactoring while maintaining the current behavior and implementing new functionality.


Thus, the order of work to eliminate technical debt is determined by the order of business tasks in the backlog.


The “business priorities” principle has another application. One of the common problems that developers who strive to write well suffer from is the difficulty of dedicating time to optimizing performance, improving maintainability, or other things that are not directly included in the work plan. There is almost always a business need for these improvements. Who doesn’t want the system to work faster, more stable, and be cheaper to maintain? All these benefits can be assessed and, based on this assessment, tasks for improvement can be placed in the backlog, along with any others.


So if you want to optimize performance, but instead have to fix another boring bug, perhaps you simply do not know how to explain the benefits of optimization in a language that the product owner can understand.

3. Leave the code cleaner than it was before you

Almost any code, except the one written very recently, lags a little behind the current idea of ​​beauty in the field of style and architecture. When you need to change code as part of a task, it is considered good practice to make all the safe improvements that are possible in the affected area. What could it be?

  • Bringing modules to the current style.
  • Changing internal variable names to more understandable ones.
  • Simplify implementation while maintaining behavior.
  • Local refactorings that do not introduce large-scale changes to other modules.

These improvements are expected to make the code better, but not significantly increase the cost of development or testing.


Due to this principle, the quality of the code gradually increases in the background, even in those places where no separate refactorings were planned. Moreover, the more often we work on a certain part of the system, the better the code for this part. A nice contrast to projects where the developer spends the most time on the parts with the worst code.

4. No matter what happens, the system must remain in working order.

One of the basic principles of SCRUM says that at the end of each sprint the system should reach a stable state.


“By the end of the sprint, the increment should be ready, which means it meets the Scrum Team's readiness criteria and is ready for use. It should be ready to use, regardless of the product owner’s decision to release it or delay it.”

Any work to eliminate technical debt is done in compliance with this principle.


Large transformations are necessarily decomposed so that any individual stage can be completed in one sprint. For example, we changed the build system in two stages (Angular 1.x: creeping webpack, lurking grunt)


We work with VCS according to principles close to classic gitflow. Development is carried out in feature branches, testing is carried out there. As a rule, such a branch does not last longer than one two-week sprint. A branch that lives longer almost always results in additional costs.


Our experience clearly confirms this pattern. Every time we failed to complete a large refactoring in two weeks, it was a pain and suffering. And the longer the task was and the longer the open branch lived, the slower the work went and the more problems there were.


The need to always be a few steps away from a stable release creates one of the most difficult and interesting engineering problems - finding the optimal decomposition of strategic plans. Large-scale changes can be broken down into separate, independent steps. It is advisable to start receiving benefits as early as possible. The better this breakdown of work is carried out, the greater the chances of bringing the job to completion.

What our process looks like

Once per release we do a detailed review of the technical backlog:

  • We close irrelevant stories (lost relevance, made as part of something else, duplicates).
  • We update the description where the vision of the issue has changed.

When business stories appear on the horizon, a technical analysis is done and all technical stories that would help in implementation are associated with the business story.


In preparation for sprint planning:

  • We check the connections between technical and business stories.
  • We link all related bugs to technical stories that can be fixed cheaply in the same place.

How to form the technical part of the backlog

When I took on the role of lead on the team, I asked each developer and QA what improvements to the product they most wanted to make. Most of the requests were related to technical improvements to the platform and refactorings. As further experience showed, all the key technical problems of the product were included in this set of wishes. So you can use this practice to quickly build a technical backlog from scratch or get a general idea of ​​the state of technical debt in a new project.


The current filling of the backlog with technical tasks occurs due to the practices described above and does not require separate efforts or analysis. In addition, new ideas for technical improvement of the product are added to the backlog. This is done by any team member who came up with such an idea. The main thing at this stage is not to lose the idea. Clarification and determination of priority occur later, during work planning.

conclusions

  • Technical debt is inevitable.
  • For most projects, eliminating technical debt is a good investment of effort.
  • If technical debt is not addressed, the development speed will gradually approach zero.
  • The temptation to throw everything out and write again can kill or seriously cripple your project.
  • The benefits of eliminating technical debt should be framed in terms of business benefits, otherwise there is a risk that tasks to create new functionality will always be considered more important.
  • Tasks to eliminate technical debt are worth managing. Such tasks are no different from other project tasks in terms of accounting, planning, and prioritization.
  • Situations regularly arise where you can reduce technical debt and solve a business problem at the same time cheaper than doing it separately. These opportunities must be used.
  • Thoughtful and timely updated code style conventions and review processes help slow down the emergence of new technical debt.
  • Short iterations are as useful for refactorings as they are for developing new functionality.
  • The team usually knows where the technical debt is in the project and how bad it is. It is worth using this knowledge when forming an idea of ​​​​the technical debt of the project.

In my answer I will touch upon not only the Great Houses, but also some other houses about which I was able to obtain information.

1.Starkey - "The winter is coming". Means that peace and security are temporary and illusory; one should always be prepared for disasters and wars in order to meet danger fully armed. In Westeros, winter is not only a season that lasts for years, but also a symbol of difficult trials. And in fact, this motto concerns not only the House of Starks, but the entire country.

2. Lannisters- House Lannister seems to have two mottos, one confirming the formidable coat of arms -" Hear my roar!", the second, equivalent to a saying, but sounding an order of magnitude more often than the first - " Lannisters always pay their debts". The first motto can be attributed directly to the coat of arms. The Lannister coat of arms depicts lion rampant- “a roaring lion”, and the motto “Hear my roar” directly complements it, it is also evidence that the lion is the king of beasts, and the Lannisters have a high position in society. The saying "A Lannister always pays his debts" is primarily associated with the Iron Bank of Braavos "The Iron Bank will always get what's due." Secondly, "A Lannister always pays their debts" means that the Lannisters never forget those who helped them and that the Lannisters never forgive the wrongs done to them.

3. Baratheon - "We are furious". originally belonged to the Durrandons of Storm's End. Orys Baratheon (the illegitimate brother of Aegon I the Conqueror), having killed Argilac the Arrogant, the last Lord of the Stormlands, adopted his motto. But the motto was translated too literally. Gives a logical translation of the motto" Anger is our element", with an explanation of its meaning " Anger is our element, which means: when you make us angry, you throw the fish into the sea, where it feels great.“That is, for the Baratheons, a violent display of emotions at the expense of cold reason is not a vice.

4. Greyjoy - "We don't sow"The Greyjoys are mostly pirates. The territory of their lands is located on bare rocks and sand. The motto of this house is a direct message that the Greyjoys do not work on the land (which really does not exist). They do not sow anything and do not grow, they rob those who have crops and spoils, since they do not and cannot have their own.

5. Targaryen - "Fire and Blood". The Targaryen motto can be interpreted in two ways. The first - Aegon the Conqueror and his two sisters, on three dragons, subjugated Westeros, which is called “with him and the sword.” The second option - (the above-mentioned sunsetsolitude) - " Targaryens are dragonborn, they have the blood of Ancient Valyria and dragons, as well as a bonus of immunity to fire, and tame dragons. When the Targaryens say Fire and Blood, they remind those who have suddenly forgotten about it."

6. Arryns - "Tall as honor"On the one hand, the House of Arryn, following the example of Jon Arryn, cared about preserving honor. Jon could not be intimidated or bribed. And in the lands of Westeros it was impossible to find anyone who cared more about preserving honor than the Arryns. But after Jon's death , probably another option is more applicable - aristocratic arrogance, disdain for those of lower status, they say, “where are you from us.”

7. Tarly - "First in battle"The House of Tarly has given birth to many great warriors and outstanding generals, as this motto confirms.

8. Tully - "Family, duty, honor"House Tully is loyal above all to its family ties. Duty and honor come after them, but family comes first. House Tully supported Rob Stark in the War of the Five Kings, for which they paid.

9. Martells - "Unyielding, unbending, unyielding". A model of pride and inflexibility. The Martells are the only house that the Targaryens could not take by force. And from the behavior of the characters of this house it is quite obvious that they are headstrong and unshakable. They do not need the laws of the Lords, the approval of the Kings, they are on their own, but clearly show that they are not ready to give up.

10. Tyrell - "Growing up, we get stronger". The motto of the Tyrell house was confirmed by their army, the number of which could not be compared with any army in Westeros. The Tyrells also had a “cushion” in the form of the wealth they had accumulated. Considering that the coat of arms of this house depicts a rose, a parallel can also be drawn with it From a small sprout to a huge rose bush. So the members of the Tyrell house, gradually accumulating strength, developed and strengthened their positions. However, as Olenna herself said, they are not warriors at all.

11. Bolton -"Our blades are sharp". This motto serves rather as a warning to the enemies (and not only) of the Bolton family. Representatives of this house have a gloomy reputation; in books they even wore cloaks made of human skin and decorated the walls of their castles with it: “A naked man has no secrets, but a skinned man and even more so." "Our blades are sharp" - apparently can also mean blades for skinning flesh.

12. Mormont - "Here we stand". The motto, which, according to sunsetsolitude, is also incorrectly translated into Russian." Here we stand - can mean “Here are our lands,” which in turn means “A small but proud island that doesn’t bother anyone, but can define itself for itself. Here are our lands, remember this when you come here, we will warned." Or it can be translated as “On this we stand” - which would be a direct indication of the strength of the Mormont’s stubbornness"

13. Frey - "We stand shoulder to shoulder"The Freys valued family ties and the inviolability of this word, which is what this motto reflected. From there, Walder Frey had an unspeakable grudge against Rob Stark, who broke his promise to marry his daughter, which led to sad consequences.

"A Lannister always pays his debts." © FFG ( Jason A. Engle)

"Lannisters always pay their debts"(Also: "A Lannister always pays his debts" listen)) is a popular saying in the Seven Kingdoms about House Lannister and a favorite expression of Tyrion Lannister. It is no less famous than the “official” motto of the house, “Hear me roar!” This expression has a double meaning. On the one hand, it means that the Lannisters, as the richest house in the state, are always ready to pay bills and thank those who helped them, or promise rewards in the future - you can always count on the generosity and commitment of the “lions”. But this motto also has a second, threatening meaning: the Lannisters do not forget the insults inflicted on them and will definitely take revenge on the offenders.

In the mouth of Cersei Lannister, the saying sounded in a speech directed against Tyrion himself - Cersei accused her brother of intrigues against her and Joffrey and tried to blackmail the captured Alaya. Later, having found herself at the head of state, Cersei used the same words to justify her decision to stop paying public debts to the Iron Bank of Braavos - the Lannisters always pay their debts, and this debt will be paid sooner or later. She later mentioned the saying in a dialogue with Balman Birch and Falisa Stokeworth, promising them a reward for their help, and then sent the Tyroshi who tried to deceive her to the executioner with the words “The Lannisters pay their debts, and you will pay too.”

Tywin Lannister mentioned the saying in a conversation with Tyrion, justifying the need to give Harrenhal to Petyr Baelish, since he himself wished it. Tyrion himself immediately repeated the words about debts, demanding a reward for himself for his services as Hand. Shae repeated the saying, reminding Tyrion of his promise to put her back in the town house. Having learned about the Westerlings' defection to Robb Stark, Tyrion thought to himself that Tywin would certainly punish the traitors, and remembered the saying.

Jaime Lannister reminded Urswick of her, trying to seduce him with wealth, and later, having lost his hand, he repeated the saying to himself, fueling his thirst for revenge and desire to live. He told Brienne of Tarth that he saved her from rape in gratitude for the sinking of Robin Rieger's galley at the beginning of their journey, again recalling the saying. He later repeated these words in a conversation with Varys, thus explaining his desire to free Tyrion. After removing Edmure Tully from the scaffold at the walls of Riverrun, Jaime thought to himself, “The Lannisters are paying their debts, and you are the only coin I have left.”

Edmure Tully himself recalled the saying upon learning of Rickard Karstark's murder of Willem Lannister and Theon Frey. Roose Bolton, speaking of his intention to leave Harrenhal and leave it to Vargo Howth, said “The Lannisters are not the only ones who pay their debts.” Jaime repeated the saying when he bade farewell to the Brave Boys when leaving the castle, hinting that he would take revenge on them, and then, returning to the castle for Brienne, he addressed the same words to Vargo Haught, saying that he would receive a ransom for both Jaime and Brienne

Technological debt management practices in a single team


About a year ago, our team moved from a phase of rapid feature growth to a more fluid development with a focus on improving quality. At this point, our products have accumulated a noticeable amount of suboptimal solutions, ugly code, and outdated libraries. Something had to be done about all this.


To date, we have managed to build a process that makes the fight against technical debt predictable, painless and inevitable.


What we got as a result:

  • The team is happy. The release retrospective regularly includes positive points about improving technology and reducing technical debt.
  • For several quarterly releases in a row, we were able to increase functionality without increasing the number of lines of code in the project. Removing unnecessary code and simplifying what was needed reduced the size of the code base for existing functionality. And this reduction roughly coincided in scale with the new code implementing the new functionality.
  • During refactorings and upgrades, the product is always in working order. Every two weeks we release a fully working interim release.

Let me tell you how we achieved this.

What is technical debt

My working definition of technical debt is the amount of work that needs to be done to make a project meet the team's vision of what is great. Note that technical debt can arise not only due to the liberal use of crutches in development, but also due to changing ideas about beauty. For example, common industry practices have changed. Or developers fell out of love with OOP and fell in love with functional programming. Or the once fashionable framework is no longer a cake and it has become difficult to find specialists who would like to write on it.


However, the main cause of technical debt is entropy in all its diversity. Disabled unit tests, outdated comments that lost touch with the code, unsuccessful architectural decisions, implementation of features that no one uses anymore, a foundation for a future that has not come, and much, much more.


It follows that the appearance of technical debt is inevitable in any long-lived project.

When technical debt is not a problem

Why is technical debt bad? It increases the cost of further development due to a number of factors:

  • The speed of implementing new functionality is reduced.
  • The likelihood of regressions when correcting defects increases.
  • The development process becomes less predictable and therefore less manageable.
  • The process of introducing a new developer into the project is lengthening.

This loss is sometimes called "interest on technical debt"


There are situations where these losses are cheaper than eliminating technical debt:

  • The end of the project's life is near. Note, this is not the end of adding functionality, but the moment when you can stop wasting programmer efforts on support too. This category also includes one-off prototypes, one-off demos for exhibitions, etc.
  • The value of development time now is much higher than expected in the future. Urgent fixes to a fixed deadline, startups that are running out of money from the next round of funding, etc. In such cases, fixing technical debt can be delayed until the heat of the moment has cooled. There are projects that do not get out of a state of emergency, but the advice from this article will still not help them.

What to do with technical debt? Failed approaches

Approach No. 1. “We don’t have time, the release must be submitted yesterday”

The desire to meet tomorrow's deadline at any cost, to the detriment of development speed the day after tomorrow.


Sometimes a prefabricated structure made from crutches is an objectively correct choice. In my practice, this was most clearly expressed when making demo versions for exhibitions. The date of the event is strictly fixed; if you didn’t make it in time for an important exhibition, the next attempt will be in a year. In this case, you can display the product “out of your hands”, carefully avoiding all bugs. As an engineer, it’s unpleasant for me to do such projects, but the crutches in them are justified.


When you make a product that will last a long time, everything is different. Meeting the deadline due to dubious technical solutions is an expensive pleasure. The total cost is:

  1. from the implementation of the crutch itself,
  2. from its subsequent replacement with a full-fledged solution,
  3. from the suffering of having a crutch in between the previous points.

The second point is very easy to underestimate, and there is a risk of not thinking about the third, the most expensive one at all.


When you meet a tech lead with a twitching eye at a conference, it may turn out that it was the nightmare of endlessly debugging a design made from crutches that brought him to this state.


Approach No. 2. “Yes, here we need to throw everything out and write it again”

The worse the technical debt situation, the stronger the temptation to bury the entire project code and write everything again. This is one of the classic mistakes that can kill the entire project.


The topic is so well covered in the famous article by Joel Spolsky that I see no point in presenting my own arguments.

Approach No. 3. “We’ll refactor at night and on weekends so that the manager doesn’t find out.”

Arguing the need to eliminate technical debt in terms of business benefits is not always easy. The development team may be tempted to go around the rough edges and start a major refactoring on the spot. This can be done during non-working hours, in pauses between other tasks, or “on the tail” of other tasks by inflating estimates.


What's bad about it? Oh, a whole bunch of things:

  • Reduced transparency undermines trust between management and the team. Often subsequent attempts to correct the situation by imposing discipline and tightening the screws will lead to a further deterioration in teamwork.
  • An entrenched situation in which the priorities of the team and management are conflicting causes demotivation on both sides.
  • The fruits of refactoring are included in the product in unpredictable ways and cause regression bugs where they are not expected. In conscious teams, this leads to a sudden and unplanned load on QA. In the unconscious, it goes into production and breaks down there.

After the team uses this recipe, management’s eyes begin to twitch.

Our principles

1. Add technical tasks to the general backlog

There are a number of patterns in the life of tasks in projects:

  • A task that is not in the backlog has less chance of getting into work.
  • A task without a clear formulation has less chance of getting into the work.
  • A task that cannot be estimated with a high degree of confidence has less chance of getting into the work.
  • A large task will wait longer in the queue than a small one.

Maxim Dorofeev talks about these things very well in his “Empty Inbox Technique”


To prevent technical debt from accumulating, work to eliminate it should be completed taking into account the principles listed above.


All tasks, except the smallest ones, are listed in the backlog. This way they have a chance to be done not only in their free time, but also as part of the planned work. In addition, such tasks are more difficult to completely lose sight of - the backlog is looked at more often and more closely than at TODOs in the code, pieces of paper on the monitor, abandoned wiki pages, tea-stained napkins with diagrams and other sources of information.

  • If there is a non-trivial TODO in the code, it contains a link to the task in the backlog. We check compliance with this principle at code review and do not accept complex TODOs without references.

    There may be drama behind the comment.

    Once, next to such a TODO it was written: “Crutch. Product Owner made me do it. Remove as soon as possible."

  • When a developer realizes that some place requires refactoring, he creates an issue in the backlog.
  • When a developer has a desire to improve the platform, he creates a task in the backlog.
  • Long-term architectural plans are put into the backlog in the form of separate tasks as soon as there is enough certainty about at least the first steps.

As long as such changes remain inexpensive in terms of development costs and the amount of testing required, we can gradually improve our code base without interrupting business objectives or introducing additional risks.

2. Plan technical stories based on business priorities

If a tree fell in the forest, but no one heard it, was there a sound? If there is bad code in a project, but that module will never need to be changed, is there technical debt?


I believe that when a programmer finds it unpleasant to look at some old module, this in itself is not a very big problem. Much worse is what happens when you need to add new functionality to this module or expand the old one. Compared to making changes to well-written code, such tasks are more likely (and more likely to exceed the original estimate) and contain more bugs. Sometimes much more. To protect ourselves from these types of problems, we try to schedule refactorings so that they are done before writing new functionality in the same place.


If functionality changes and refactorings seem small, they can be done together. The empirically selected size of the task for which this approach will be optimal is 3 days of work for one developer or less. When it is clear that there is more work, it is divided into refactoring while maintaining the current behavior and implementing new functionality.


Thus, the order of work to eliminate technical debt is determined by the order of business tasks in the backlog.


The “business priorities” principle has another application. One of the common problems that developers who strive to write well suffer from is the difficulty of dedicating time to optimizing performance, improving maintainability, or other things that are not directly included in the work plan. There is almost always a business need for these improvements. Who doesn’t want the system to work faster, more stable, and be cheaper to maintain? All these benefits can be assessed and, based on this assessment, tasks for improvement can be placed in the backlog, along with any others.


So if you want to optimize performance, but instead have to fix another boring bug, perhaps you simply do not know how to explain the benefits of optimization in a language that the product owner can understand.

3. Leave the code cleaner than it was before you

Almost any code, except the one written very recently, lags a little behind the current idea of ​​beauty in the field of style and architecture. When you need to change code as part of a task, it is considered good practice to make all the safe improvements that are possible in the affected area. What could it be?

  • Bringing modules to the current style.
  • Changing internal variable names to more understandable ones.
  • Simplify implementation while maintaining behavior.
  • Local refactorings that do not introduce large-scale changes to other modules.

These improvements are expected to make the code better, but not significantly increase the cost of development or testing.


Due to this principle, the quality of the code gradually increases in the background, even in those places where no separate refactorings were planned. Moreover, the more often we work on a certain part of the system, the better the code for this part. A nice contrast to projects where the developer spends the most time on the parts with the worst code.

4. No matter what happens, the system must remain in working order.

One of the basic principles of SCRUM says that at the end of each sprint the system should reach a stable state.


“By the end of the sprint, the increment should be ready, which means it meets the Scrum Team's readiness criteria and is ready for use. It should be ready to use, regardless of the product owner’s decision to release it or delay it.”

Any work to eliminate technical debt is done in compliance with this principle.


Large transformations are necessarily decomposed so that any individual stage can be completed in one sprint. For example, we changed the assembly system in two stages ()


We work with VCS according to principles close to classic gitflow. Development is carried out in feature branches, testing is carried out there. As a rule, such a branch does not last longer than one two-week sprint. A branch that lives longer almost always results in additional costs.


Our experience clearly confirms this pattern. Every time we failed to complete a large refactoring in two weeks, it was a pain and suffering. And the longer the task was and the longer the open branch lived, the slower the work went and the more problems there were.


The need to always be a few steps away from a stable release creates one of the most difficult and interesting engineering problems - finding the optimal decomposition of strategic plans. Large-scale changes can be broken down into separate, independent steps. It is advisable to start receiving benefits as early as possible. The better this breakdown of work is carried out, the greater the chances of bringing the job to completion.

What our process looks like

Once per release we do a detailed review of the technical backlog:

  • We close irrelevant stories (lost relevance, made as part of something else, duplicates).
  • We update the description where the vision of the issue has changed.

When business stories appear on the horizon, a technical analysis is done and all technical stories that would help in implementation are associated with the business story.


In preparation for sprint planning:

  • We check the connections between technical and business stories.
  • We link all related bugs to technical stories that can be fixed cheaply in the same place.

How to form the technical part of the backlog

When I took on the role of lead on the team, I asked each developer and QA what improvements to the product they most wanted to make. Most of the requests were related to technical improvements to the platform and refactorings. As further experience showed, all the key technical problems of the product were included in this set of wishes. So you can use this practice to quickly build a technical backlog from scratch or get a general idea of ​​the state of technical debt in a new project.


The current filling of the backlog with technical tasks occurs due to the practices described above and does not require separate efforts or analysis. In addition, new ideas for technical improvement of the product are added to the backlog. This is done by any team member who came up with such an idea. The main thing at this stage is not to lose the idea. Clarification and determination of priority occur later, during work planning.

conclusions

  • Technical debt is inevitable.
  • For most projects, eliminating technical debt is a good investment of effort.
  • If technical debt is not addressed, the development speed will gradually approach zero.
  • The temptation to throw everything out and write again can kill or seriously cripple your project.
  • The benefits of eliminating technical debt should be framed in terms of business benefits, otherwise there is a risk that tasks to create new functionality will always be considered more important.
  • Tasks to eliminate technical debt are worth managing. Such tasks are no different from other project tasks in terms of accounting, planning, and prioritization.
  • Situations regularly arise where you can reduce technical debt and solve a business problem at the same time cheaper than doing it separately. These opportunities must be used.
  • Thoughtful and timely updated code style conventions and review processes help slow down the emergence of new technical debt.
  • Short iterations are as useful for refactorings as they are for developing new functionality.
  • The team usually knows where the technical debt is in the project and how bad it is. It is worth using this knowledge when forming an idea of ​​​​the technical debt of the project.

CATEGORIES

POPULAR ARTICLES

2024 “kingad.ru” - ultrasound examination of human organs