inheritance - Derivation, composition, constructors, interfaces and TDD -
when developing tdd objects 'grow' code evolves . first include functionalities, , later add new ones. can composition and/or inheritance.
at same time, use interfaces (for test, , production code) ensure low coupling, dependency inversion, dependency injection , mocking.
how manage this?
i mean, example: have created class, , must include new attribute (for example, person can have e-mail). do?
- modify class, adding new attribute: must add new constructors. if modify existing constructors must refactor test involved, not production code. try keep constructors add new attributes, @ end become unusefull, obsolete (only exist because of tests), complex logic of 'constructor calling constructors' (or use kind of 'factory')
- derive class: more compilant ocp. if make real tdd, small steps, if derive, starting simple class, end terribly complex , somehow unneccesary inheritance. , besides, it's supposed must test public exposed members. so, again, base classes become protected, must refactor tests access public ones.
- compose: composing has no problem constructors, not solution. our current example.
and similar thing happens, in way, interfaces.
so, code grows, constructors interfaces must evolve. , have 3 precepts in mind:
- you should avoid refactor tests.
- the production code must not keep 'code intended testing' (i.e. constructors)
- isp states use specific interfaces. code grows many of them become unnecesary, used testing (i.e. mocking) classes that, in many cases, should protected or private.
so, said... how can manage while developing tdd? know it's question long answer, so, if refer article, or resource
changing tests ok
what you're describing (person has email) change in specs. unit tests supposed be specs, it's normal have change them when introducing new data.
this kind of test fragility trade off quality, necessary evil.
don't overengineer
by trying apply ocp, inheritance , composition add 1 field, you're making things more complicated yourself. pointed out, results in production code monstrosities sake of testing, , have modify tests anyway.
ocp might if you're adding new behavior in family of existing behaviors, it's not case here.
make changes more manageable
there are tactics make tests more resistant small changes, implemented at test level, not in production code. besides, opportunities spottable if duplication in tests, during refactor step of tdd cycle instance.
one of them encapsulate "system under test" creation in factory method , call instead of normal constructor in each of tests. make of parameters optional default value. allow make changes (e.g. add email field) in 1 place , tests benefit it. doesn't save modifying test suite, in 1 place.
Comments
Post a Comment