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:
Vervolgens komt er een wijziging, en na een aantal stappen komen ze met de volgende code:
Hierbij wordt het volgende stuk tekst gegeven:
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?
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:
Echter is dit in strijd met een stukje wat eerder in het hoofdstuk geschreven wordt: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.
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.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!
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?