Expect change & Agile principles, patterns and practices

Pagina: 1
Acties:

  • DEiE
  • Registratie: November 2006
  • Laatst online: 16-08 19:21
Disclaimer: Ik ben momenteel student en heb nog niet binnen een bedrijf dat Agile-methodieken gebruikt gewerkt.

Op dit moment ben ik in het boek Agile Principles, Patterns, and Practices in C# link aan het lezen, een mooi boek dat fijn wegleest.

In een hoofdstuk van dit boek gaat het over een applicatie waar onderhoud aan gepleegd moet worden. In het boek is een extreem simpele applicatie gebruikt als voorbeeld. Het gaat om een applicatie die gegevens kan inlezen, en weer kan uitvoeren. De initiële applicatie kan enkel van een keyboard lezen en uitvoeren naar een printer:

C#:
1
2
3
4
5
6
7
8
9
public class Copier
{
   public static void Copy()
   {
      int c;
      while((c=Keyboard.Read()) != -1)
          Printer.Write(c);
   }
}

Vervolgens komt er een wijziging, en na een aantal stappen komen ze met de volgende code:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface Reader
{
   int Read();
}
public class KeyboardReader : Reader
{
   public int Read() {return Keyboard.Read();}
}
public class Copier
{
   public static Reader reader = new KeyboardReader();
   public static void Copy()
   {
      int c;
      while((c=(reader.Read())) != -1)
         Printer.Write(c);
   }
}

Hierbij wordt het volgende stuk tekst gegeven:
Instead of trying to patch the design to make the new requirement work, the team seizes the opportunity to improve the design so that it will be resilient to that kind of change in the future. From now on, whenever the boss asks for a new kind of input device, the team will be able to respond in a way that does not cause degradation to the Copy program.
The team has followed the Open/Closed Principle (OCP), which we describe in Chapter 9. This principle directs us to design our modules so that they can be extended without modification. That's exactly what the team has done. Every new input device that the boss asks for can be provided without modifying the Copy program.
Note, however, that when it first designed the module, the team did not try to anticipate how the program was going to change. Instead, the team wrote the module in the simplest way possible. It was only when the requirements did eventually change that the team changed the design of the module to be resilient to that kind of change.
One could argue that the team did only half the job. While the developers were protecting themselves from different input devices, they could also have protected themselves from different output devices. However, the team really has no idea whether the output devices will ever change. To add the extra protection now would be work that served no current puprose. It's clear that if such protection is needed it will be easy to add later. So, there's really no reason to add it now.
Echter is dit in strijd met een stukje wat eerder in het hoofdstuk geschreven wordt:
Unfortunately, so many other programs use the Copy program now that you can't change the interface. Changing the interface would cause weeks and weeks of recompiling and retesting. The system test engineers alone would lynch you, not to mention the seven people in the configuration control group. And the process police would have a field day, forcing all kinds of code reviews for every module that called Copy!
Ik heb moeite om deze laatste twee stukken te begrijpen, wellicht omdat ik de ervaring uit de "echte" wereld hierbij mis. Mij is altijd verteld dat stukken waar verandering verwacht kan worden op zo'n manier gebouwd moeten worden dat deze verandering makkelijk door te voeren is, zoals in het tweede codevoorbeeld bij de reader gedaan is. Aan de ene kant zeggen ze dat het ontwerp er complexer op wordt als alle mogelijkheden voor verandering beschermt worden (in dit geval door de interface), maar aan de andere kant zeggen ze dat de interface niet veranderd moet worden, wat dus wel gebeurd is toen de interface erbij geplaatst is in het tweede codevoorbeeld.

Mijn vraag is voornamelijk hoe er in de praktijk met dit soort dilemma's omgegaan wordt. Wordt er in eerste instantie al rekening gehouden met punten waar kans op verandering is wat de software complexer maakt, maar waar wel makkelijker veranderingen doorgevoerd kunnen worden, of wordt software op de meest eenvoudige manier gemaakt, en de mogelijkheid tot verder veranderen erin gebouwd op het moment dat blijkt dat het element veranderd?

Acties:
  • 0 Henk 'm!

  • chime
  • Registratie: Januari 2005
  • Laatst online: 09-09 12:46
Bij agile ontwikkel je alleen wat echt nodig is, op de meest eenvoudige wijze.
Niet meer, niet minder.
Code aanpassen voor mogelijke toekomstige wijzigingen is vaak extra werk, extra testen en extra complexiteit en raadt men dus af.

Voor interfaces is het belangrijk om te weten dat deze gebruikt kunnen worden door andere applicaties.
Lees: ga je de interface zelf aanpassen dan impacteer je mogelijk alles wat je interface gebruikt en de kans is groot dat jij niet weet wie de interface allemaal gebruikt. Lees: dikke shit.

Maar in het voorbeeld kan je zien dat de interface niet veranderd is.
De externe gebruiker roept nog altijd Copier copy() aan ... enig nadeel is nu wel dat alleen keyboard input verwerkt gaat worden. Alleen hebben ze het bij deze aanpassing gemakkelijker gemaakt op de input door andere readers te laten verwerken.

Het doet me een beetje denken aan een tekst uit de boek Refactoring van Martin Fowler.
Maak je een stuk code waar je van denkt dat het mogelijk herbruikbaar is ... dan laat je het zo.
Copy / Paste je dat stukje code naar een andere plaats ... dan laat je het ook zo, maar je onthoudt het wel.
Pas de 3e keer ga je het eruit trekken en effectief refactoren.

Reden hiervoor is dat code generieker maken ook extra werk kost en vaak meer kost dan het opbrengt (ik heb al genoeg projecten gezien met tientallen klasses die mogelijk wel eens gebruikt zouden kunnen worden ... maar die niks doen)

Het is geweldig dat je een Copier zou maken die zonder probleem van elke mogelijke input kan lezen en naar elke mogelijke output kan sturen ... maar gebruik je allen keyboard en printer ... dan ben je geld/tijd van je klant aan het verspillen.

Acties:
  • 0 Henk 'm!

  • DEiE
  • Registratie: November 2006
  • Laatst online: 16-08 19:21
Bedankt voor je reactie.

Als ik het goed begrijp, is het een probleem als je je interface moet aanpassen doordat er dingen gerefactored moeten worden (In het voorbeeld moet er immers wel wat gebeuren, in de programma's moet nu de keyboardreader worden meegegeven. In het boek wordt het duidelijker besproken). In de praktijk kost het echter meer tijd om jezelf in te dekken tegen al deze mogelijke veranderingen dan het kost om de applicatie goed te refactoren zodat hij deze veranderingen aankan als dit nodig zou zijn.

Op school ligt de nadruk voornamelijk op het maken van een goed ontwerp en een flexibel systeem, en dit soort dingen komen zo goed als niet aan bod. Je hebt me geholpen om het een stuk beter te begrijpen :).