Original article: http://coolshell.cn/articles/3649.html
There was a lot of controversy over agility and thoughtworks in China in an article about over-hyped technologies and concepts before the Spring Festival, the Chinese company thoughtworks also sent me an email asking me to talk to me in person. I was expected to be challenged and criticized by agile fans. I also replied to many comments. However, all my replies are about China's thoughtworks consultants and their consulting methods. I have not commented much on the specific content in the Agile Methodology. Therefore, I would like to discuss the specific practices in the Agile Methodology (I have discussed the advantages and disadvantages of Pair Programming in the past ).
So let's talk about TDD this time. This is the favorite thing of thoughtworks fans in China and agile. In my original article, I removed TDD from over-hyped technologies, because I still think TDD has some truth. However, looking back on my experience, I don't really like TDD either. I want to tell you this article,TDD is not as beautiful as it looks, it is very difficult to control, and this method has a paradox.
TDD Introduction
TDD, short for test driven development, is a software development process introduced by agile "eXtreme Programming. The development process starts from the test case of functional requirements. First, add a test case, and then run all the test cases to check whether there are any problems, and then implement the test case function to be tested, then run test case to check whether there is a case failure, then refactor the code, and repeat the above steps. The idea is to ensure two things:
Ensure that all requirements are taken care.
In the process of increasing code and refactoring, you can check whether all the functions are correct.
I do not deny some useful parts of TDD. If we start with test case, we can immediately know what the code is like, this allows us to get feedback on our implementation ideas earlier, so we are more confident in restructuring and re-designing to make our code more correct.
However, I want to remind you that,TDD and unit test are two things.. Many may confuse the automated unit test (for example, xunit series) and TDD software development processes. In addition, some people may advocate"TDD allows you to implement top-down DesignFor more information, see Richard Feynman, Challenger, software engineering on this site. The challenger from NASA tells you the danger of a top-down design.
TDD difficulties
Below are some of the issues that I think TDD is not easy to control, or even a little impossible (if fans of TDD or consultants of thoughtworks and you advocate TDD, you can ask them the following questions)
Test scope Determination. TDD development process. Generally, test case is written first. There are many types of test cases, including functional, unit, and integration ......, The most difficult part is how much test case should be written.
If you write too high level, you don't know what went wrong when your test case fails. you have to spend a lot of energy debugging code. What we hope is that it can tell me which module has the problem. There is only a test case of high level. Isn't it the test link in waterfall?
If the write is too low level, the problem is that you need to spend two times to maintain your code, one copy for test case, A copy of the implemented function code.
In addition, if you write too low level, your requirements are variable according to agile's iterative development. In many cases, our requirements are the assumption made by developers themselves. Therefore, the more detailed the test case is, the more advanced your maintenance costs will be once the demand or assumption changes.
Of course, if I implement a function or module, I certainly know where the scope of test is, and I also know the degree to which my test case needs to be written. However,The paradox of TDD lies in that you write test case before implementation, so how can you ensure that the test case at the beginning is suitable for your subsequent code?? Don't forget that programmers gradually understand the needs and systems in the development process. If the test case is adjusted while the test case is implemented, why not write the test case after the implementation? If so, it is not TDD.
Focus on testing, not design. This may be a drawback of TDD, as mentioned in ten good programming ideas-"unit test won't help you write the good code ", in the actual operation process, I saw many programmers rush to work or cope with work,As a result, the code is written to meet the test, ignoring the code quality and actual needs.. Sometimes, when we refactor the code or fix the bug, the programmer even thinks that the code is correct as long as all the test cases pass. Of course, fans of TDD will have the following arguments:
Code quality can be ensured through Pair programming.
At the beginning, the Code must satisfy the correct functions, followed by refactoring and optimization. TDD makes your refactoring and optimization not at the cost of functionality.
That's right, but in theory. The operation may not get the expected results. 1) "Pair programming" does not guarantee that neither of the two pairs will meet the purpose of the test, because during the reconstruction or optimization process, once the programmer sees that n more test cases are failed, people will be nervous, and you will not naturally fix your code to make all test cases pass. 2) In addition, I don't know how to program. My general practice is to think about various feasible implementation solutions from the overall situation. For some difficulties, I need to actually program and try it. Finally, I want to weigh the comparison, select the best solution for implementation. However, it is often anxious to implement a function, which usually leads to rework. The subsequent refactoring is basically due to the insufficiency of preliminary considerations and the rewrite. Therefore, in the actual operation process, you will find that many times refactoring usually means rewriting, because of the "non-functional" requirements, you have to re-design. Re-design often means that you have to rewrite many test cases of low-level, so you only dare to write test cases of high level.
TDD leads to a large number of mock and stub. Believe me, test case is not necessarily so easy. For example, interconnection with other teams or system interfaces, or modules that are not very clear about the implementation, etc. So you need to do a lot of mock, Stub, and even fake functions in your code for simulation. Obviously, you need to do a lot of assumption. Therefore, you find that managing and maintaining these mock and stub has become a burden. The most terrible thing is that it is not a real integration test, mock in your test case is probably wrong. You need to rewrite them.
Maybe you will say that even if TDD is not used, we do need to use mock and stub during normal development. That's right! This is true, but remember, we decided to place a mock or stub in the implementation code, instead of doing it before the code implementation.
Test case is not as simple as imagined. Like waterfall, every link of waterfall depends on the correctness of the previous link. If we do not understand the requirement correctly, the TDD, test case, and our code will all be wrong. Therefore, in TDD, test case is the most important link in development. The quality of test case will directly lead to the correctness and efficiency of software development.However, TW consultants and agile fans seem to naturally think that TDD can better understand the needs than waterfall. If this is the case, use TDD for requirement analysis, and then directly use waterfall..
In addition, some test cases are not necessarily so easy to write. You may spend 80% of the programming time on the design and implementation of a test case (for example, test concurrency). Then, the demand changes, you have to rewrite test case. Sometimes, you will find that writing test case is actually no different from designing it. You also need to consider the correctness, scalability, accessibility, maintainability, and even reusability of your test case.If the test case we developed is used to ensure the correctness of our code implementation, who will ensure the correctness of our test case?? Do I also need to pair or code review when writing test cases? Software development is a bit like a long-distance race. If energy is spent in the first half of the journey, it will be hard for the second half of the journey.
Maybe TDD is really over-hyped, but I have seen a good project developed using TDD, but that project is relatively simple. In more cases, I see the rigid TDD, so it's not surprising to hear the complaints from programmers-"since TDD is used, the workload is even greater ". Of course, this cannot blame them. TDD is a method that is hard to control. Here is a sentence for software development managers --"When a problem occurs in your software development, just like a bug-fix, the first thing is to find root cause and then solve it in case by case, do not change a new development method immediately because of any problems.". Believe me, most of the problems are people and managers, not methods.
Virtual Forum: How beautiful is TDD?
Http://www.infoq.com/cn/articles/virtual-panel-tdd
TDD is not as beautiful as it looks