Luxoft Training has prepared for you a translation of the article by Joe Reinsberger, a well-known Canadian software development consultant,
“Discipline or Tests. Pick one?
Joe Rainsberger is the author of many works on information technology. For his contribution to the development of flexible methodologies, he was awarded the highest award from the Agile community - the Gordon Pask Award in 2005 (in the first year of creation of the award). He is the founder of XPDay (North America). JUnit Receipes: Practical Methods for Programmer Testing, a book by Joe Rainsberger, has become world famous. Joe has been practicing flexible methodologies since 2000, and during that time his articles on Agile development have been published in leading developer journals, including IBM DeveloperWorks and IEEE Software. In IEEE Software magazine, Joe is the editor of the “Not Just Coding” column.
Discipline or tests. Choose one?
Would you rather have a disciplined programmer or a strong test suite?
Recently, one of the clients asked me this question, and I am not sure that I gave a fairly good answer. I will try to do it here.
')
I see advantages in both cases, so, unfortunately, I can not briefly answer this question. On the one hand, a disciplined programmer will make sensible decisions, even if he does not do the same thing that I would have done. If I trusted the general discipline of the programmer, I would feel comfortable trusting him (her) to produce high-quality work, by which I understand the constant flow of valuable working code. On the other hand, if I trust in the discipline of a particular programmer or programmers, they will produce artifacts that I cannot easily consume, and when they disappear, my constant flow of valuable working code will also disappear. This will turn into a Truck Number problem (Bus number, Bus factor).
Since I use a good test suite to reduce the unpredictability of the marginal cost of functions
(When we say that we take care of design “for economic reasons,” I believe that we mean exactly that. Note that “marginal cost” simply means “The cost of the next function.”) , Then it may make sense to require programmers who supply me with these functions to supply tests to preserve the possibility of maintaining the code base in a cost-effective way and without them.
So what would I prefer? I'm going to find out in the process of writing this article. It really depends on a lot. Let me examine the question, and perhaps, with a sufficient number of attendant factors, I can make a choice.
What does “disciplined” mean?
Suppose that the programmers we are talking about have a high degree of discipline, but they do not write tests. What do I need from them (assuming that I cannot demand tests), which would allow me to comfortable adopt their code base? I have a few ideas.
- I need to know where in the code I look for what I need.
- After I find what I need, I need to know either (1) that I have found everything that I need, or (2) that I can understand where to look next.
- I have to be sure that if I change something, it will not cause sudden changes in other places.
It becomes very similar to following the
four elements of simple design . And that leads me to another question.
If programmers write simple code (such as in Four Elements) without tests, what else do I need that would allow me to comfortably adopt their work?
It's funny that this question never arose. If the system is well developed, in accordance with the Four Elements, then it seems to me that it is relatively easy to add tests after development. This follows from the basic concept that the Four Elements induce us to write the code being checked, and according to the definition of “verifiability”, I should not have any particular problems when testing the code being checked.
I would prefer not to spend extra time adding these tests, but I would have endured it. It becomes a solution based on commercial considerations: if I pay $ 100,000 to add tests to your code, you’d better save me more than this $ 100,000 compared to the best possible option, including writing tests . As long as you get it, what is my right to complain?
I now do not take into account that I strongly doubt that I could ever hire programmers who can write simple code without tests, except by chance. I remain open to this opportunity.
Time is not really money
Well ... I see one potential problem. The cost of taking such a simple code base includes not only money, but also time, and if
I can refund the money ,
time will never . I need to consider the cost of delay to add tests to this hypothetical codebase. Fortunately, I can amortize these costs over the life of projects that support this code base, which makes it probably
the cheapest inherited code in history .
I think I would have experienced it too.
So, suppose that I have a simple code that saved me more money in the creation process than I would spend on adding tests after it was created. Am I missing anything important without getting the tests along with the code?
About code base
I will definitely need a one-page document describing the overall design of the system — the five most important things — as well as which functions, according to programmers, have already been created and which will be created next.
Presumably, as a client of this hypothetical product, I will understand quite well the product, the subject area, and the functions that in my opinion have already been created. (It would not hurt to compare my perception of what has already been done with their perception.)
This brings me to the first version of the final list of things that I need to trust in the code base written by “disciplined programmers” who do not write tests.
- A short document describing the overall design of the system, the functions that, according to programmers, have already been created, and the functions that programmers are going to create as follows.
- A code base that irrefutably demonstrates that programmers have made this code simple according to the four elements of simple design.
- The constant speed of creating functions that covers the time (relatively small) time I need to add tests, since I myself maintain the code base.
I think having all these things, I can agree to adopt the code base from a group of programmers who do not write tests.
Of course, this does not mean that I advise you to bring all your tests to fire in order to see what comes of it.
And what about the opposite situation? Suppose I have a strong test suite, but my programmers are not very disciplined. What are the risks, and how can I reduce or compensate for them?
What is this “strong test suite”?
What do I expect from a “strong test suite”? I would like to have mostly micro tests written in the style of joint and contract tests
(I have a very broad opinion on the topic “Integrated tests are nonsense,” but I have not yet found the strength to write it. Now I am doing it very slowly. When “Maybe I'll write this book. In the meantime, this is my last talk on this topic) , with a pinch of functional tests written in the style of the most caring practitioners of behavior-driven development. These functional tests will help me understand the functions, and micro tests will give me the confidence needed to make changes to the code.
This is the problem: the
cost of understanding and maintaining these tests most likely corresponds to the cost of understanding and maintaining the final code. This makes sense, since, most likely, the same people wrote both. (I understand that I cannot reasonably assume this, but, nevertheless, I will.)
Since the programmers in question are supposedly not as disciplined as I would like, we can expect that there will be problems in the final code. In general,
where I find problems in the final code, I can expect to find a close connection between the tests and the details of the implementation of this final code. I can expect a large amount of
indirection without abstraction . In short, I can expect well-tested, well-covered inherited code. Theoretically, I can save this inherited code,
but I will have to face the usual inconsistencies of the cost of saving code.Probably, I will be able to find the
best total cost of code rescue with the same inconsistency as with legacy code without tests. This seems intuitively obvious, considering that in some cases the tests will be so closely related to the implementation details that I have to throw away the tests and start anew
(I assumed that the programmers did not write the final code depending on the tests. I understand that this assumption is risky , but I find the alternative too terrible to think about it) . As the tests reveal the implementation during testing, they hide the pronounced details of the main aspects of the behavior, and as a result I will work on archeology in order to discover the main aspects of the behavior, with or without tests.
I do not want to portray the situation completely horrible. Of course, the presence of tests increases the likelihood that I will be able to change part (possibly large) of the code safely, although not confidently, at least at the beginning. Probably, designing will be unpleasant for me, but changing the project will probably be simpler than with a typical base of legacy code. On the other hand, the
need to write tests for legacy code gives me such an opportunity to understand the purpose of the code, what a simple reading of overly detailed tests can never give. I have to prepare myself for the possibility that the need to write tests from scratch for legacy code is part of the process, not a defect.
Wow. I did not expect this. (Seriously)
I think I would prefer disciplined programmers.
It seems that I would prefer to have disciplined programmers who do not create tests, less disciplined programmers who provide a strong set of tests. No, this is not a trick. (“A simple project passes all tests, but if there are no tests, then the project is obviously simple ...” No.) Yes, I would like to have tests too, but if someone can achieve good results without tests, then I do not have the right impose their methods on them. I have to admit that this surprises me, because in the past I probably wrote that I would prefer tests. Then it seemed like a good idea. I cannot explain the shift in my thinking.
Despite this,
please write tests , no matter how disciplined you think you are. I believe that writing tests and accompanying refactoring helped me a lot to develop discipline, and I still insist on writing tests. So if I hired you, I would demand the same from you.
Epilogue
My friend
Michael Bolton told me that this article reminded him of the problem of implicit knowledge. In particular, tests (actually “checks”) can only reflect someone’s ideas about what the system should do, and thus, they will surely miss some piece of information that, according to Murphy’s law, will become important for us the wrong moment. And at this moment we will definitely want us to have access to the programmer, and not just to the checks / tests.
Indeed, the checks seem to have coded at best a relatively recent snapshot of what the randomly chosen version of us thought about the functioning of the product, being limited by our ability to formulate these thoughts (given our skills and energy at that moment). To put it in this way, it seems obvious that I would rather choose disciplined people, and not the checks themselves!
On July 7 and 8, Joe Rinesberger conducts an online workshop on the topic
“Value-Oriented Approach in Software Development”