6 ms·
> Be Defensive - They're out to Get Your Code! - Defensively assert about the state of parameters passed in methods, constructors, and mid-method. If someone ca
by jve 5y ago
> Be Defensive - They're out to Get Your Code! - 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! Be aggressive in preventing this: rule your code with an iron fist! (And remember: it's not paranoia if they really are out to get you.)
This seems nuts to me? Sacrificing guarantees for the sake of testability? I mean defensive coding is one of good tools to fail early and with meaningful error messages and confidence on state within your method.
Moreover there are tons of points just to enable mocks'n'stuff. Why not just go higher up the abstraction layer and test things functionally there? It's more useful IMHO than some state object that may never be true in real life.
It reads like chasing some code coverage metric with fake state. When in reality, you may still get nullreferenceexception because your assumption on false state was incorrect. Or some method call there may fail with unhanled error code or whatever. It doesn't take branches for fully covered code to fail.
IMHO unittests are useful, but in limited scope.
- dgb23 5y agoIt seems like you need comprehensive unit tests if your implementations are shallow and grant few guarantees. I like TDD-style example tests to create a fast feedback loop during initial development or refactoring though.
- marginalia_nu 5y agoIn my experience, if you find you need to check every parameter because your code keeps blowing up from all the bad parameters its getting, the problem is at the source of the bad data. Checking input everywhere is a questionable treatment of the symptom, it won't fix the bigger problem that some part of your code is producing invalid output. It's a lot harder to fix bad data as a consumer of that data, than as its producer. This primarily applies to internal code. For external APIs there is no such thing as too much validation.
- jve 5y agoI don't trust my future self that I'll start feeding in bad data. Of course there are some boundaries, but not too deep. I've started more of defensive coding when I've read that for a software I forgot how it called - there was security audit which find no important security flaws. Because their ideology was to not trust the input, even if its your input. Today your assumptions are correct, tomorrow, because of changes, they can be incorrect. I'll post link here if I find it. I think I read it on HN few years ago. Edit: A-ha, here it is. Dovecot. HN Article: https://news.ycombinator.com/item?id=13407233 https://news.ycombinator.com/item?id=13407233 and https://wiki.mozilla.org/MOSS/Secure_Open_Source/Completed#dovecot https://wiki.mozilla.org/MOSS/Secure_Open_Source/Completed#d... > The Cure53 team were extremely impressed with the quality of the dovecot code. They wrote: "Despite much effort and thoroughly all-encompassing approach, the Cure53 testers only managed to assert the excellent security-standing of Dovecot. More specifically, only three minor security issues have been found in the codebase, thus translating to an exceptionally good outcome for Dovecot, and a true testament to the fact that keeping security promises is at the core of the Dovecot development and operations." Practices documented in source: https://github.com/dovecot/core/blob/master/doc/securecoding.txt#L13 https://github.com/dovecot/core/blob/master/doc/securecoding... > Don't rely on input validation. Maybe you missed something. Maybe someone calls your function somewhere else where you didn't originally intend it. Maybe someone makes the input validation less restrictive for some reason. Point is, it's not an excuse to cause a security hole just because input wasn't what you expected it to be. Perhaps it's just my way of dealing with "I know that input is validated". Yeah, defensive coding can get verbose, but makes me feel confident. + The NASA Coding Guidelines of states: > Each calling function must check the return value of nonvoid functions, and each called function must check the validity of all parameters provided by the caller. > The code's assertion density should average to minimally two assertions per function. /just extracting useful bits of advices from veterans
- marginalia_nu 5y agoMy experience is that this type of coding actually introduces more fragility and sensitivity to change. If you validate conditions you think will be true, but do not explicitly depend upon at every level the data passes through, you'll find your application randomly blowing up when those conditions change. I think the problem boils down to a violation of separation of concerns. Defensive code inevitably concerns itself with ensuring guarantees about state that is the concern of other modules.
- sidlls 5y agoThis seems nuts to me? Sacrificing guarantees for the sake of testability? TDD zealots tend to not care about efficiency, maintainability, readability, or any of a number of very important characteristics of a program if it interferes with the kind of false-security testability they are zealots about.
- rmbyrro 5y agoWhen I need internal checks and flexible testing, I create testing types. So, instead of "Null", I let the test pass a "TestIgnore" type object and react to that accordingly. These types should be clearly meant to be used ONLY in testing environments.