onsdag den 18. marts 2009

Scrum fra dag 1..eller?

Software arkitektur handler om facon og form hørte jeg den anden dag. Hvor er faconen så henne – ja den ligger i de abstrakte base klasser. Og hvad kan man så bruge det til? – jo det er fra arkitekturen at projektplanen fremtræder. Det er her mellem streger og kasser at de parallelle spor findes. Det er her man får overblik over hvad der kan udvikles parallelt og hvor der er afhængigheder som udgør de kritiske stier som skal betrædes for at få det til at lykkedes.
Rækkefølgen hvor i hvordan software skrives er derfor ikke ligegyldig, det gælder om at starte det rigtige sted for at opnå parallelitet i projekt planen og dermed udnytte de hænder man har til rådighed bedst muligt. Svarende ligger i arkitekturen fordi vores traditionelle lagdelte arkitektur har afhængigheder. Enhver form for relation mellem software, hvad enten det er en webservice, et c modul, en java klasse giver en afhængighed. Så kommer spørgsmålet når man så tager sit første sprint, hvad skal vi lave? Det ved product owneren. Han har en plan med sprintet. Og vi tager den plan, laver vores backlog, bryder ned til tasks – men hvad skete der med paralleliteten?. Kan vores product owner gennemskue arkitekturen og se at her er et godt sted at starte fordi det betyder at vi om en eller to uger kan rampe up og starte en masse i parallel og give projektet fart. Næppe. Jeg har aldrig set en product owner der kunne. Kunden i den anden ende kan slet ikke. Og er sikkert også ligeglad, kunden forventer at vi gør hvad vi kan for at levere hans produkt så hurtigt så muligt. Derfor sander scrum til. Det er simpelthen langsommere at lave software på den måde, fordi vi ikke tager højde for at noget kan udvikles parallelt.

UML og scrum:
I UML findes der 6 forskellige måder at beskrive afhængigheder på i software. 4 omhandler kommunikation og 2 struktur.

De 4 der omhandler kommunikation er:
Afhængighed
Associering
Aggregering
Og komposition.

De 2 der omhandler struktur er:
Generalisering og realisation.

Afhængighed, ligner en association, så den tager vi bagefter.

Man laver en association ved at erklærer den man associerer til i sin egen klasse. Hvis det skal kompilere skal man altså mindst have et skelet af den man associere til, ellers er erklæringen ugyldig. Og hvorfor så lave sådan en? – jo typisk skal man jo bruge de metoder som den associerede klasse tilbyder, så hvis det skal kompilerer skal man altså også som minimum have metoderne i den klasse erklæret. Der er altså en rækkefølge ved denne type af afhængighed. Noget man er nød til at implementere før man kan bruge det.

Afhængigheden laves ved at gøre det samme, men nu er erklæringen af den man associerer til ikke i sin egen klasse, men derimod i en metode i sin egen klasse. Den er altså lokal og ikke som sådan en del af klassen selv. De er mere dynamiske og opstår runtime og forsvinder igen når metoden returnerer. Men igen er der en rækkefølge.

Aggregation, er en specialisering af association. Men i praksis har det ingen betydning. Koden er fuldstændig mangen til en association!.

Komposition er igen en specialisering af association. I C++ kan man se forskellen ved at den klasse man har en komposition til er erklæret som en variable og ikke en pointer. I Java er der ikke har pointere, er der igen ingen forskel på koden.

Fælles for disse er altså at noget skal findes før det kan bruges i andre klasser. Og det er man nød til at tage højde for i sin planlægning af sit projekt. Et rigtigt godt udgangs punkt er skelettet. Det gør at koden kan kompilerer, man kan hurtigt få sin struktur implementeret og teste om softwaren har det rigtige flow igennem den ”use-case” man ønsker, inden man fylder algoritmer og funktionalitet på.

Hvis man derimod går efter funktionalitet og begynder at fylde det ind, inden skelettet er på plads sker der tit det at de metoderne ikke bliver generelle nok til at håndtere andre use cases af lignede art. De andre udviklere på teamet går i stå, de kan ikke kompilere deres kode, fordi de mangler metoder. Når metoderne ikke bliver generelle nok skal der ”refaktorering” til. En metoder skal have en argument mere på, og det kan ikke kompilerer, da alle andre kalder den samme funktion med et nu forkert antal parametre. Det griber om sig.

De strukturelle afhængigheder som der findes 2 af i UML er følgende.

Generalisation er arv, det vil sige at man arver en del af de egenskaber en anden klasse har. I C++ er det bare et enkelt : og i Java, extends der gør det for en. Hvad man arver er forskelligt afhængig af hvordan den klasse man arver fra er skruet sammen. Men faktum er at klassen skal være der, før man kan arve. En finurlig ting ved arv er polymorphi, som kommer fra græsk og betyder at have flere former. Det basale er at hvis den klasse man arver fra har erklæret en metode virtual, ja så kan man overskrive den. Man skal dog holde sig til den samme erklæring, parametre etc. Man ser det mange steder i den virkelige verden, feks i banker hvor vi alle har forskellige kontoer med forskellige renter, som beregnes på forskellige måder.
Hvis man bare går efter en enkel funktionalitet, behøver man ikke bruge det. Man kan sagtens i sprint 1 lave en opsparings konto der kan beregne renter og i sprint 2 lave en real kredits konto der kan beregne renter.

Realisering er typisk brugt hvor man ønsker at gøre brug af det framework ens platform tilbyder. Feks på android er det flittigt brugt til interaktion, swipe, scroll etc. Hvor frameworket kalder din klasse og fortæller dig hvad der foregår mellem brugeren og skærmen, hvor man trykker og hvor hurtigt han flyttede fingeren. I Java er det simpelt, især med moderne editorer, man skriver implements også det interface man vil lytte til. I C++ er det heller ikke så svært, man laver en base klasse hvis metoder er pure virtual og nedarver fra den. Effekten er den samme, der er nogle metoder som man er tvunget til at implementere i sin egen klasse. Poly morphisme og realisation hænger nøje sammen. Feks kunne det betyde at man aldrig kan lave en konto klasse, der ikke kan beregne renter. Altså en sikkerhed for at et interface overholdes.

Det er åbenlyst at det er i disse beskrivelser af afhængigheder imellem de software komponenter, klasse eller moduler vi laver at nøglen til genbrugbarhed, fleksibiliteten til at udvide ligger. Men ved vores produkt owner det?, og kommer det til at stå i produkt backloggen? – næppe. Derfor kan man ikke køre Scrum fra dag 1.

Ingen kommentarer:

Send en kommentar