6 ms·
How to write untestable code
- DannoHung 17y agoSome pretty darn good advice in here. This might be slightly embarrassing, but it actually makes me appreciate the value of Factories; something I always thought was a little overkill for anything but GUI code.
- viraptor 17y agoThey are overkill. They're java man's substitute for lambdas. But if all you have is java, everything looks like an object.
- tjpick 17y agoexcept ints, chars and bools.
- jrockway 17y agoFurther proof that premature optimization is the root of all evil. (Compilers can automatically solve the performance issue of boxed native types now, so there is no reason to provide the programmer with unboxed types. But of course Java does because... it's Java.)
- _sh 17y agoI don't understand this. Are you using closures as types? If so, what can they offer that factories can't? Trying to understand, genuinely curious.
- viraptor 17y agoThey offer the same functionality (more or less)... Factory objects just feel like overkill - usually they carry no state of their own, so why are they objects? If you could pass around functions, you could just use them instead. x_factory_proto :: GlobalParams -> InitParams -> X ... x_factory = x_factory_proto some_params
- viraptor 17y agoCould someone explain this one? > Be Defensive [...] Defensively assert about the state of parameters passed in methods, constructors, and mid-method. If someone can pass in a null, you've left your guard down. You see, there are testing freaks out there that like to instantiate your object, or call a method under test and pass in nulls! I'm not sure what he wants to change. Surely if the code would crash when I pass a null as an argument, it's better to make it throw the exception as early as possible. You can test that by asserting an exception when you call that_func(null);. Why is that a bad thing? (Or did I misunderstand him?)
- req2 17y agoIn the comments he admits that public APIs should be defensive, but internal APIs should be 'known good' via testing.
- psnj 17y agoCould someone explain: "Be Defensive - They're out to Get Your Code! - Defensively assert about the state of parameters passed in methods, constructors, and mid-method."? which, desarcastified, I take to mean: "Don't defensively assert about the state of parameters passed in methods, constructors, and mid-method." Specifically: "You see, there are testing freaks out there that like to instantiate your object, or call a method under test and pass in nulls" Isn't it the case that a calling a method with (say) null parameters where they are supposed to be non-null should raise an exception? Isn't an assertion failure reasonable in this case? I understood and agreed with a lot of the other stuff (although it struck me as a bit dogmatic) but this one I don't get.
- japherwocky 17y agoI think what the author is getting at is testing a particular method on an object without having to mock up all the data required by the entire object. I guess? Agreed that the whole article would be more useful without the sarcasm.
- viraptor 17y agoSo that's basically allowing operations on a half-broken object, just so that you can test it without creating all the dependencies?... I see how it might be useful, but I just can't agree with that. The tests are not the goal - a working product is. That's just making a trade-off between less lines in a test -vs- code that doesn't explode mid-transaction when that null suddenly occurs in a real-world scenario. If I'm supposed to write my code properly, testies should not be too lazy while writing the tests.
- omouse 17y agoIt's no longer a unit-test once you're putting the object into the living system. It becomes a system test and then you might as well test the whole system instead of faking things with mockups.
- zenocon 17y agoIf you use Java, EasyMock makes this a non-issue. I have found that with a test framework like EasyMock, you no longer have to jump through so many of these goofy tdd hoops. You can mock methods, return values, thrown exceptions, parameters to methods to another object inside a method, etc. It still doesn't warrant writing crap code using anti-patterns, but nevertheless, it makes life more bearable by putting the focus back on the logic at hand and less on trying to follow the tdd mantra of design.
- txxxxd 17y agoIt's too bad Java/C++ were designed after unit testing became commonplace. Some of the advice here will actually improve your production code but a lot of this is just a case of the programmer having to work around the language. For example, the advice to not "instantiate objects using new in the middle of methods" wouldn't be a big deal if if your test code could easily instruct the compiler to replace the concrete object with a mock when the test is run.
- ori_b 17y agoNothing prevents that being implemented in existing compilers. In fact, you can already do that in Java with class paths.
- JoeAltmaier 17y agoA little too vague - don't use if? switch? Surely they are useful. Better to advise against putting application logic into the wrong object - which is what I THINK they are arguing against.
- ardit33 17y agoJesus, basically don't worry about the product, just worry about having testable code. I thought "having testable" code, is never the end, maybe the means perhaps, but not necessary, If you have done mobile development, you know you have to break most of these rules at some point. Sorry, I'd rather have a shipping/peformant product, than one that is a hog, but makes OO purists happy, and is easy to test. At the end of the day, keeping your customer happy, that is the end game.
- deleted 17y ago[deleted]
- deleted 17y ago[deleted]
- arohner 17y agoShould be "How to write untestable code in Java". Makes me glad I'm not writing Java, fewer than half of these are problems for me.
- jriddycuz 17y agoI'm pretty sure this was copied word for word from the employee guide of the firm that originally wrote the software I now trudge through every day. Except it wasn't sarcastic. And I think there was some other rule in there about avoiding spacing in the source code at all costs.
- flyingbertman 17y agoHow about a million lines of code in VB6?
- adamc 17y agoMostly assumes object-oriented programming, of course.
- Deestan 17y agoWith a smug smile on my face, I notice that most of this list is impossible to do in Haskell.
- yread 17y agoWhat's wrong with Create Utility Classes and Functions/Methods - For instance, you have a String which is a URL you're passing around (obeying "Use Primitives Wherever Possible"). Create another class with static methods such as isValidUrl(String url) if the function is a deterministic function (I guess it could be implemented as a simple test against regex) why is is difficult to test? I get that its better to use the system one or your own URL class, but thats really about OO and not testing!
- roam 17y agoThe keyword is "static". You'll often want to use a mock implementation rather than connecting to a remote server, checking for a 404 error and returning true or false - every time you run your tests. Loosely coupled objects will allow you to do that, but how would you redefine the behavior of something static?
- rincewind 17y agoGreenlight if-branches and switch statements OO cowboys will want to have a whole polymorphic soup of collaborating objects Of Course! When I implement, say, Bubble Sort, I do not implement the classes BubbleList with the methods sort and addObject: anObject and BubbleObject with the method bubbleMaybe: aBubbleList, just to see my tests for BubbleObject fail when I switch to Quicksort.