Codefreeze and Continuous Delivery

    imageTraffic jams begin at intersections when traffic flows conflict. While one thread is moving, the other is forced to wait. Something similar happens when the next release of a software product is released: in order to release a product of decent quality, you have to stop development.

    There are no programs without errors. While doing something useful, we involuntarily introduce into the code what we were not going to. Sometimes surprises arise at the junction of seemingly unrelated changes. Here's a great example of how optimizing your mouse driver prevents you from updating your address book in Outlook . Therefore, there always comes a time when the team is focused exclusively on testing and fixing bugs. Adding new features at this time is prohibited.

    But the sources of new requirements, wishes and other Wishlist are not impoverished. While the release is stabilizing, the queue at the adjacent traffic light / backlog of the product is only growing. It turns into a classic cork. How to resolve this conflict?

    The famous Magdeburg Water Bridge is an impressive demonstration of the successful resolution of the conflict. Ships move in independent streams without interfering with each other.
    image

    Extreme programming suggests fixing bugs as they are discovered, without stopping development. And in general, it is necessary to program without errors. A cool method, I like it, but, unfortunately, the developers still program with errors. I wonder why why? One will have to ask on occasion. In general, traffic jams in this case do not occur, but a certain number of accidents / annoying errors inevitably seep into the release. If the cost of correcting a leaked error is low, then this approach is fully justified.

    But for the rover software, I would not recommend it.


    The other extreme is the classic Waterfall, which calls not to mix one with the other. First, design everything, then carefully implement it, carefully test it, correct errors and transfer the result to the customer.

    The approach is quite reasonable in terms of cost optimization, but often not very effective in the face of uncertainty. When creating new products, it is often not possible to reliably find out what and how should be implemented. Much is being done “on trial” and redone subsequently. With the successive passage through the phases from the idea to its verification, too much time passes.

    Moving along the beaten track full of trial and error, it seems to me that we managed to find a reasonable compromise between these two extremes - to provide the flexibility necessary when developing new products, while maintaining a high level of quality. In this article I would like to share our experience, maybe it will be useful to someone.

    First, we tried working in short iterations, which resulted in a working, tested version. The limited iteration scope helps the team concentrate and not be distracted. In order to have time to eliminate all the roughnesses to the finish of the iteration, it is customary to lay some time to stabilize the code. At this time, serious changes to the code are not made, only errors are fixed.

    A stabilization period is necessary, it limits the number of changes in the code and makes the process convergent. In practice, it turned out that a significant part of the team is bored at this time: there are not enough errors for everyone. Of course, there is always work beyond the limits of iteration, but changes cannot be made - stabilization is ongoing. And at the beginning of the next iteration, testers are bored waiting for new errors ... Management, seeing that the workers are idle, threatens to transfer them to other projects.

    The next step was an attempt to work according to the Kanban method. Tasks go in a continuous stream, after the completion of each task, a version is obtained. But the hope of quality destroys the basic law of organic chemistry: if you mix a barrel of honey and a spoon of shit, you get a barrel of shit. Full testing of the version after each task could save the situation, but it turned out to be too expensive both in terms of labor costs and time.

    It would seem that the situation is hopeless ... But who said that changes need to be made where stabilization is taking place?

    Now we are working on the model of “three levels of instability”:

    1. The development branch is poorly controlled stability. Here tasks are done "for the future", which will not be included in the current release.
    2. The release branch is a controlled reduction in volatility. The set of changes that will be implemented in this thread is limited and rather rigidly fixed.
    3. A stable version is a condition fixed at some point with an acceptable level of quality. Changes are made extremely rarely and very small (hotfixes)

    It works like this.

    From the product backlog, we recruit release tasks in such a way as to do it in a month. This is our current sprint. The team begins to implement the release, and closer to its end, when there are few changes and there is not enough work at all, smooth preparatory work begins for the next sprint. The work is carried out in a separate branch in the gita, in a separate section of the kanban board in Jira. When the scope of the current release is completed, tested and stabilized, the release branch becomes stable, the development branch becomes the base for the next sprint, and the development branch freezes in anticipation of the end of the next sprint.


    Excuse me, someone will say, but then there are no actual edits in the development branch. And with errors it’s inconvenient, they have to be corrected in two branches at once. To avoid such problems, we agreed to precede any work in the development branch by injecting changes from the release branch. After this procedure, the development branch contains all relevant developments and bug fixes.


    Changes from the development branch do not get into the release until stabilization is complete. This makes it possible to complete the release and transfer the stable version to the sales department. And before the start of the next release, all the developments fall into the release branch.


    Now we have a continuous stream of tasks and a non-blocking procedure for stabilizing the release, which allows us to release high-quality versions without stopping development.

    The next point of application is to shorten the stabilization period to reduce the gap between branches and reduce the overall TimeToMarket time.

    Also popular now: