3 ms·
Refactoring is not (necessarily) generalization. I am interested in how you decide you have seen enough examples to generalize (to actually doing arithmetic in
by sorokod 8y ago
Refactoring is not (necessarily) generalization. I am interested in how you decide you have seen enough examples to generalize (to actually doing arithmetic in this case) and what makes you trust your judgment at that point while rejecting your judgment initially.
- mpweiher 8y agoOf course, arithmetic is a somewhat silly example, because we generally tend to have arithmetic built in, and we all know how arithmetic works. "Refactor to remove duplication" is absolutely a standard step of TDD. How you do it is up to you. This is not an automated process, it requires (design) skill and good judgement just like any other programming. I recall once seeing Beck look at two loops that were quite dissimilar: they had different for structures, and different contents, which is pretty much nothing duplicated except the word "for", and the fact that they were looping - differently - over the same collection. He changed the second loop to loop the same way the first one did. This required changing the body of the loop to skip over the items toward the end of the collection, since the previous version only did the front of the collection. Now the for statements were the same. "Well, gotta eliminate that duplication, he said, and moved the second body into the first loop and deleted the second loop entirely. Now he had two kinds of similar processing going on in the one loop. He found some kind of duplication in there, extracted a method, did a couple of other things, and voila! the code was much better. http://wiki.c2.com/?OnceAndOnlyOnce http://wiki.c2.com/?OnceAndOnlyOnce What this approach does is move most of this type of tricky design work to a phase of development when you are not also trying to figure out what the program is trying to do or how to do it. Instead, while you are doing this design work, the behaviour of the program remains fixed and you have tests to make sure that's actually the case. Having the code remain functionally identical (in terms of the tests) is a lovely safety net to have while you are doing fancy coding acrobatics. If you find you're in a dead-end, revert, check that the tests are still green and try again, with the knowledge you've just gained. I guess this is something that older developers are more attuned to, because they have been humbled by code enough to appreciate the limitations of their cognitive faculties. > rejecting your judgment I trust my judgement, always, and am wary of my judgement, always. But I also listen to the code, and I just don't "remove duplication" until there actually is duplication. http://wiki.c2.com/?YouArentGonnaNeedIt http://wiki.c2.com/?YouArentGonnaNeedIt https://en.wikipedia.org/wiki/Rule_of_three_(computer_programming) https://en.wikipedia.org/wiki/Rule_of_three_(computer_progra... https://blog.codinghorror.com/rule-of-three/ https://blog.codinghorror.com/rule-of-three/
- sorokod 8y agoThanks for the time you took to reply. Just to get something quickly out of the way, yes - it is a silly example but this is the one you chose or at least chose to defend. I will be interested to see an an equivalent of "return 9" in an example that is not silly. While you make good points about the value of refactoring and having a well tested code, they are not specific to TDD. Nor do they address my question. It seems to be a fundamental property of TDD that a developer is invited to reduce her mental capacity - up to a point, "return 9" or as you suggested "if ((a == 10) && (b == 2)) return 12". Then something unexplained happens e.g.: "refactor the add method to handle all those cases with less code, by removing the case-handling and doing arithmetic.". What exactly happened here? Why is the developer can now use that big brain of hers 100%, realize that special case handling is not the way to go, and write "a + b"?
- mpweiher 8y agoThere is no switch between "brain on" and "brain off", what you describe as "a fundamental property of TDD" to "reduce mental capacity" is just a misunderstanding on your part. > Then something unexplained happens I am not sure why you think this is "unexplained", as it is spelled out in detail in every TDD introductory text. What there is is a switch between (a) trying to get the tests to pass (tests are red) and (b) trying to refactor the code (tests are green). In both cases, you use your full brain, in case (a) you use it to find the minimal code to pass the tests. If you think finding minimal code is a "brain off" activity, well that's a whole different discussion, but I refer you to Saint-Exupéry[1] and Blaise Pascal[2], for starters. And in each case you use code as forcing functions for other code. The tests force you to write the production code. Writing only the least possible production code that passes the tests forces the tests to actually test what you want them to test. If you write code that does significantly more than what your test requires, you won't have test coverage for that excess capability. And so if the rest of your program exercises that excess functionality and you break it, your program will break without your tests giving you a warning. Also, the silliness of the example is of course what makes it a good illustrative example. If we had to first become domain experts with s shared understanding of some random domain, it would make talking about TDD itself much harder. It does require the ability and willingness to use it as an illustrative example. [1] https://www.goodreads.com/quotes/19905-perfection-is-achieved-not-when-there-is-nothing-more-to https://www.goodreads.com/quotes/19905-perfection-is-achieve... [2] https://quoteinvestigator.com/2012/04/28/shorter-letter/ https://quoteinvestigator.com/2012/04/28/shorter-letter/