On 02.05.2013 16:12, Brad Jorsch wrote:
On Thu, May 2, 2013 at 9:36 AM, Daniel Kinzler daniel@brightbyte.de wrote:
- The "composition" approach, using:
[...]
Disadvantages:
- more classes
- ???
- A lot of added complexity
The the number of classes, and the object graph, some. Not in the code though. In my experience, this makes for less complex (and less surprising) code, because it enforces interfaces.
But I agree that we should indeed take care though that we don't end up with a maze of factories, builders, etc.
To be honest, I was (and to some extend, still am) reluctant to fully adopt the composition style, mainly for this reason: more classes and more objects means more complexity. But I have come to see that a) for testability, this is simply necessary and b) the effect on the actual code is rather positive: smaller methods, less internal state, clearer interfaces.
- The "subclassing" approach, using:
[...]
- Instead of making a bunch of one-public-method classes used only by
ApiQueryLangLinks, just put the logic in methods of ApiQueryLangLinks.
Advantages:
- Everything is in one file, not lost in a maze of twisty little classes.
"everything in one file" seems like a disadvantage to me, at least if the things in that file are not very strongly related. Obvious examples of this being a problem are classes like Title or Article.
But you bring the question to a point: does the increased granularity needed for proper unit testing necessarily lead to a "maze" of classes, or to cleaner classes and a cleaner object structure? Of course, this, like everything, *can* be overdone.
But maybe it's a question of tools. When I used a simple editor for MediaWiki development, finding and opening the next file was time consuming an annoying. Since I have moved to a full featured IDE for MediaWiki development, having many files and classes has become a non-issue, because navigation is seamless. I don't care what file needs to be opened, i can just click or enter a class/function name to navigate to the declaration.
- These methods could still be written in a "composition" style to be
individually unit tested (possibly after using reflection to set them public[1]), if necessary.
* ..."could still be written in a "composition" style" - I don't see how I could test the load-with-hooks code without using the load-from-db code, unless the load-with-hooks method takes a callback as an argument. Which to me seems like adding complexity and cluttering the interface. Or we could rely on a big if/then/else, which essentially doubles the number of code paths to test.
* ..."using reflection to set them public". I guess that's an option... is it good practice? Should we make it a general principle?
Disadvantages:
- If someone comes up with someplace to reuse this, it would need to
be refactored then.
Or rewrite them, because it's not easy to find where such utility code might already exist...
-- daniel