Archive for category Designprinciper
Encapsulation and testability
Posted by alexander in Designprinciper on March 18, 2011
I’ve come across this pretty much every time when giving talks on TDD and testing, so I thought it’s time to write down my thoughts on the subject. They’re not very original, in fact not original at all, but I’ve tried to find some solid ground at least.
When writing unit tests, you soon end up in a situation where you expose a method more than “proper encapsulation” would require, only to make it testable. In Java this happens through package access, while .NET implementations may be of type internal/[InternalsVisibleTo].
This problem is less common in TDD, but sometimes I feel that I’d prefer another access modifier on my finished code. Personally, I’ve stopped caring about this long ago, but exposing more than the public interface (as in API, not the interface keyword) seems to be a big issue for many people. I’ve found two coping strategies for handling this problem:
- Use interfaces or abstract classes. They become the public part, while the implementation may have slightly more test-friendly access. Again, even this can seem offensive to some people.
- Run all tests through public methods only. This is not the best way to test-drive code, in fact it’s very poor, but it’s doable if your approach is more like developer testing and not strict TDD.
As you see, neither method is perfect, so instead I’m going to present the best argument I’ve found so far for not being overly cautious about “encapsulation” (information hiding) as defined by people who are offended by the difference between internal/package and protected, for example.
I’ve found the second best argument in the book “The art of Unit testing” by Roy Osherove. He does have a “don’t be silly argument”, but the main argument is that test code is a client of the tested API as well, and that this client should be supported. That’s a very good argument, but my favorite is given by Bertrand Meyer in the bible “Object-oriented software construction”. I need to quote here:
“[…] To prove the correctness of a module, you will need to assume some properties about its suppliers. Information hiding means that such proofs are only permitted to rely on public properties of the suppliers, never on their secret properties.”
On the same page Bertrand Meyer argues that information hiding isn’t protection in the sense of security – a physical restriction to the information. A module may very well expose all its members as public and still achieve information hiding if its formal correctness is proven using its public interface. Whether to do this or not is a project management decision, not a technical one.
I’ve found this argument very convincing and sound, and it just happens to support my personal preferences. I hope to convert some non-believers.
Domändriven design på 15 minuter och 15 sekunder
Posted by alexander in Designprinciper on October 14, 2009
Vad är domändriven design?
Igår var jag på Javaforum igen. Tyvärr var jag tvungen att gå kring sju, så jag missade två av tre presentationer, men fick pizzan i alla fall. Den första presentationen handlade om domändriven design, och talaren hade den otacksamma uppgiften att förklara vad det är på femton minuter. Inte lätt. För oss som läst Evans blev det en helt ok presentation, för man fick höra lite om praktiska erfarenheter.
För de mindre förberedda blev det svårare. Kod på svenska, nya konstiga designmönster, och framför allt – är det inte så man ska designa system? What’s the big deal?
The big deal, på 15 sekunder, är att man kan lätt förklara vad som inte är domändriven design. Låt mig exemplifiera.
Där jag jobbar säljer vi produkter som baseras på månatliga prenumerationer. Det finns bara en produkt. Det som inte är domändriven design, är design som kommer från databasen och uppåt, och där produkten är beskriven med tabellerna Product, Item och Subscription (nej det finns ingen anledning till detta förutom lättja och stajlande i SQL).
Hur kommer detta in i DDD:s ubiquitous language (annorstädes närvarande språk)? Hur kan man prata verksamhet och affärsregler kring detta?
Ny designprincip!
Posted by alexander in Designprinciper on March 26, 2009
Denna princip känner vi intuitivt till, men den sammanfattades så väl av min kollega Joakim Tengstrand när vi satt med ett content management system som är användarvänligt för webbredaktörer, men hatar alla som försöker att utöka det med lite Javakod.
När vi kom på oss med att skriva in XML, som refarerar till en XSL-transformation i ett fält kallat “Description” sade Jocke: “Jag har det som princip; är det fult så är det fel”.
I detta fall var det tämligen självklart, men principen håller även för tyngre granskning. Om vi uppfattar något som fult betyder det att vi uppfattar det som onaturligt i någon mening. Det betyder att allt arbete med det onaturliga kommer att bli dyrare i termer av anpassning, underhåll och dokumentation – alltså fel.
Dessutom, har vi fått hjärnsläpp och glömt vad t ex SRP står för, så har vi i alla fall en fallbackprincip som är lätt att komma ihåg.
Är det fult så är det fel.
YAGNI:s onda tvilling
Posted by alexander in Designprinciper on February 25, 2009
You Aint Gonna Need It är en sund princip för mjukvaruutveckling, och är dessutom naturligt integrerad i de agila metodologierna: Vi väljer den feature/story som anses viktigast för affärerna och implementerar den. Det andra får lägre prioritet, och implementeras om det behövs. För att införa ett nytt begrepp, låt oss kalla detta makro-YAGNI och likställa med vanlig verksamhetsdriven prioritering.
Lillebror, som jag självklart kallar mikro-YAGNI, är det vi hittar på Wikipedia när vi söker på YAGNI, alltså att endast implementera den funktionalitet som krävs för att lösa det omedelbara problemet, och inte ge sig på generella, framtidssäkra, gärna ramverksbaserade lösningar (på problem som ändå kommer att se helt annorlunda ut om en månad). YAGNI skyddar således mot överkreativitet och feature creeping. Man kan länge diskutera huruvida jagande att ett ‘lokalt minimum” leder till att vi utvecklar bra system, eftersom vi teoretiskt saknar helikoptervyn, men jag tror att ju bättre vi är på refactoring, desto smidigare går det att förflytta sig från design till design och forma systemet i den riktning man vill. Tror man inte på mig, kan jag dra till med ett citat av Kent Beck (tror jag): By not considering the future of your code, you make your code much more likely to be adaptable in the future”. Genom TDD integrerar vi dessutom principen naturligt i vår utveckling, eftersom ingen vill testdriva fram ett helt ramverk om resultatet bara ska bli “Hello world”.
Allt med YAGNI är såklart inte svartvitt och oproblematiskt, och den intresserade kan googla vidare (det finns ett antal relevanta invändningar), för ämnet för inlägget är tredje medlemmen i familjen: den onda tvillingen.
Den onda tvillingen frammanas så klart av onda människor. Dessa människor menar att vi kan tillämpa YAGNI-principen även på kvaliteten, och inte bara på scope. De har nämligen lärt sig att utvecklare älskar att övergeneralisera problem och gör allt i sin makt för att inte leverera affärsnytta. Verktyget mot detta är således: enhetstester – You Aint Gonna Need It, code reviews – You Aint Gonna Need It, infrastruktur för enkel automatisk deployment … Självklart är en del av kritiken befogad – ingen rök utan eld, men det jag försöker komma åt här är behovet av att utveckla den pedagogiska förmågan som behövs för att förklara vad som verkligen behövs och vad som kan tummas på… (och förstå det själv).
Gillar vi Law of Demeter?
Posted by alexander in Designprinciper on February 20, 2009
Eftersom bloggen är ny och hemlig när detta skrivs, är det ingen som kommenterar inläggen, men om detta inlägg någonsin läses, så är jag väldigt nyfiken på folks erfarenheter.
I alla år har jag tyckt att Law of Demeter har känts som en olustig designprincip. I teorin låter den vettig, men någonting har alltid tagit emot. För dem som inte kommer ihåg principen och inte orkar googla, så betyder den (i korthet) att man bara får göra anrop på ett objekts metoder, men inte dess ingående eller relaterade objekt. Alltså t ex car.turn() och inte car.getWheel().turn(). Detta får till följd att de “yttre” objektet måste tillhandahålla ett gäng delegatmetoder, som i exemplet ovan void turn() {getWheel().turn();}. Förespråkarna menar att detta är ett billigt pris för att reducera klassers kunskap om varandra och öka inkapslingen.
Mina erfarenheter kring delegatbiten är att delegatmetoder inte ser så bra ut i praktiken som i designböckerna. Man får ett gäng till synes meningslösa metoder, ökar en klass ansvarsområde och följaktligen minskar dess cohesion. Testtäckningen sjunker på klassnivå, eftersom delegatmetoder faller inom ramen för “too simple to break”. Detta är ett kosmetiskt problem, men ändå.
Å andra sidan är tanken bakom Law of Demeter att designen ska växa fram underifrån, vilket rimmar väl med TDD, vilket i sin tur med stor förmodan leder till att man verkligen först hade designat den “yttre” klassen, och sedan refactorat in de inre allteftersom de kom att behövas. I bilexemplet hade man förmodligen enligt YAGNI+TDD verkligen först implementerat turn() i bilklassen, och kanske sedan kommit på att en rattklass också behövs.
Å det tredje kan det kanske också vara bra att ha en princip som uttryckligen förbjuder spagettiprogrammering (här tänker jag främst på program skrivna i VB av någon anledning), speciellt om man lär ut programmering.
Man kan också vända på steken och fråga om trotsande av Law of Demeter är ett problem i praktiken. En någorlunda bra programmerare kommer inte att skriva spagetti, dels för att det är fult, dels för att koden blir svår att testa; det blir svårt att rigga alla relationer i testfixturen…
Enmannajuryn är långt ifrån enig, men det är ganska kul att ha strukturerat sina tankar kring denna princip i skrift. Droppa gärna en eller flera kommentarer om denna designprincip.
