applies for the specification of behavior in software, not everything in everyday life conforms elegantly to this desired level of minimalism. Sometimes, repetition AtLeastTwice
becomes necessary for various reasons. An argument may be made, however, for minimizing repetition; hence, one could argue for TwiceAndOnlyTwice
OnceAndOnlyOnce and UnitTests -- a Case for TwiceAndOnlyTwice?
is a good philosophical starting point.
But wouldn't the XP way be TwiceAndOnlyTwice
? Every concept in the code should be expressed exactly twice, once in code and once in the Unit Tests. One expression is "how you implement this concept" (and to date even the most declarative languages still require some help in the "how" department), and one expression is "how this concept should work" in the UnitTest
nlessYouHaventWrittenTheImplementationYetAndOnlyHaveUnitTests? ;-) )
does this. Instead of TwiceAndOnlyTwice
Projects declare behavior once in code, and once or more in tests.
OAOO is not philosophy. ProductionCode should specify behavior OAOO because that forces a design to improve. One must promote the access to that behavior. The book DesignPatterns says to "abstract the thing that varies". This is the inverse way to say "merge behavior that duplicates".
Having some code and a Unit Test for it doesn't 'duplicate' the code. The test only 'runs' the code, with pre-defined, pre-calculated conditions. These conditions are set to trigger an error (aka a bug) or break the code, if a 'weak point' exists (much like stress-testing an I-Beam in construction to find a weak point.) As such, a Unit Test is much like executing the code in a full-scale program, except for the fact that its soul purpose is to determine if the code is good or not.
Based on the above, the XP way wouldn't be TwiceAndOnlyTwice
See also ExtremeNormalForm
Since I first wrote the initial version of this page, I've come to understand that I seem to write tests that are far more vicious than the Unit Tests that XP advocates, and most people seem to write. If for some standard system involving a login and permissions, I have an Account and a User and Permissions and some methods for administrators to modify Permissions, I consider testing each of those in isolation just the start. If one of my criteria is that an Administrator can only hand out permissions that they themselves have, I'm not happy until I've got a test that fully creates an Administrator account (and by "fully" I mean "if I put the relevant DB records in my production database my Administrator would be able to login in and function correctly", and if that means creating a bunch of other things too so be it; it's worth it to stay in sync), fully creates a User account, and does several checks on the Administrator changing permissions on the User account, including interaction with any relevant caches and whatever other complications may develop. I want to get as close to "doing it through the real interface" as possible, too; if this is a website, I like to run the actual website code.
So, OK, XP doesn't advocate TwiceAndOnlyTwice
. But I find myself programming and thinking that way. Maybe it'd be worth talking about it from that viewpoint, then.
This seems close to ProgrammerTest
, but Programmer
Test is pretty vague on what programmer tests are, probably by design. This may be a specific instantiation of that general idea. (At least, as explained by the contents of the Programmer
Test page as of this writing. UnitTest
claims that XP now calls them programmer tests, and then the first line of ProgrammerTest
is "XP terminology, not quite synonymous with Unit
Test".) This isn't quite an AcceptanceTest
test either; it's halfway between a unit test and acceptance test.
One thing I've noticed is that just as UnitTest
ing seems to almost naturally produce a good, well-separated design, this technique seems to naturally produce a useful API. As you write these harsh tests, you find yourself writing the same setup code over and over. So you factor that setup code into a "convenience method" on the relevant classes, which in my experience often turns out to be so darned convenient that it becomes the primary API.
The other thing this has driven me to do is to produce a structure in my testing code that enables this style of development. I'm preparing a Python module I've been using for this for an initial public release (still burning it in, the original version of the module in Perl I've been using at work for months but it's got a couple of work-assumptions embedded in it), which enables the horrific-sounding "full creation of an account" above to become "data.new_account()", in a way that seems to minimize coupling of that method to the rest of the system while retaining the flexibility of setting details (via optional parameters not shown here).
I can't prove anything, but in my experience over the past year, working with this structure through some major refactorings, the apparently-obvious problem with this approach don't seem to arise; even as we did something as radical as completely rewrite our permissions systems, only tests that directly dealt with permissions were affected; everything else was fixed simply by tweaking the test account creation code.
for me means what I originally wrote above, which still seems to have survived: "Every" requirement in the system (or as many as are cost-effective to test) exists twice: Once in the code that says "how", and once in the unit tests that say "what is supposed to happen". Even if that means involving half the system; I've built a coding structure that enables me to do that without tight coupling.
So, question: Is anybody else doing this? For a long time I simply assumed
that this is what Unit Testing is, because I haven't worked directly with anybody else using unit testing. (At work, I've been the one driving
the adoption of testing, so the testing structure reflects my ideas already and can't provide a check.)
Ultimately, I'm just curious, because I've obtained enough benefits from this approach to continue doing it, but a discussion could be interesting. -- JeremyBowers
TwiceAndOnlyTwice as Applied to Security Protocols
This was to be my first new page on Wiki; however, it already exists as another topic. Anybody know the Wiki way for handling NameCollision?
... (make it look pretty. :))
The general idea of OnceAndOnlyOnce
is to say something once and it gets done. With systems that must be highly secure and are combined with the lack of universal passwords (e.g., far too many FinancialSystems?
), sometimes very good security can be obtained by saying things twice and only twice.
Take the case of sending a WireTransfer?
initiated at the receiving bank. Now then, a bank account can be created with minimal security checks (funny how long it takes to catch a bogus SSN). On creation of a bank account strong security can be established for that account; however, there is simply no guarantee that the account holder is the account holder of same name, SSN, etc. at a different bank. The obvious fix is initiate WireTransfer?
from the sending bank. Now then, sometimes that's just not possible: e.g. creating a new account with a wire transfer. Understand that some banks have no physical presence *anywhere*. Now then, send normal create account with wire transfer to initiating bank, send permit wire transfer from account to unspecified account at target bank to sending bank.
(I cannot parse the above paragraph. Entirely too many "now then"s -- it needs to be cleaned up, but I don't know how.)
Notice that a OnceAndOnlyOnce
solution does not exist because the interbank interface for WireTransfer?
s is well defined and cannot contain additional authorization information. Therefore we have TwiceAndOnlyTwice
There is some added gain: TwiceAndOnlyTwice
that actually goes a long way towards securing a difficult transaction. E.g., there is a form of TwiceAndOnlyTwice
for Security that is CallbackAuthorization
The general idea of OnceAndOnlyOnce is to say something once and it gets done.
Close, but not quite: OnceAndOnlyOnce
strives for simply writing it
, for some definition of it, in a single, well-known location for easy (potentially automated) reference. You can verify the orthogonality of "getting it done" by noting the fact that you can write lots of code/specs/whatever OnceAndOnlyOnce
, but which never actually executes nor otherwise used.
One should not confuse programming (an act of specifying
) and communicating (an act of transmitting
over a potentially noisy channel). Redundancy finds application in a wide variety of communications-related roles, to overcome signal loss in a dynamic, noisy channel and also to enforce authentication. In these roles, redundancy serves to improve the fidelity of the communication.
A program listing, meanwhile, needn't concern itself with the potential behavior of a dynamic channel. A listing exists as a static representation of an otherwise pure (set of) idea(s) -- redundancy, in this case, actually introduces
noise into the specification.
My experience says: avoid using OnceAndOnlyOnce
as an excuse to keep your tests clearly separated from your code. Generally avoid reusing code in your tests except as UUT and stubs. Duplicate funcionality if necessary. Hence TwiceAndOnlyTwice
See also: DuplicationRefactoringThreshold