Criteria voor slecht ontwerp

Het leven werkt heel eenvoudig: om slim te zijn hoef je vaak geen domme dingen te doen. Dit geldt ook voor softwareontwikkeling: in de meeste gevallen, om iets goed te doen, moet je het niet slecht doen.

De meeste programmeurs hebben ervaring met delen van het systeem die slecht ontworpen waren. Maar nog treuriger zullen de meesten van jullie de trieste ervaring hebben te beseffen dat jullie de auteurs van zo'n systeem waren. We wilden het beste, maar het pakte zoals altijd uit.

De meeste ontwikkelaars streven niet naar een slechte architectuur, en voor veel systemen komt er een punt waarop ze beginnen te zeggen dat de architectuur verschrikkelijk is. Waarom gebeurt dit? Was architectuurontwerp vanaf het begin slecht, of is het in de loop van de tijd slecht geworden?

De wortel van dit probleem is het ontbreken van een definitie van "slecht" ontwerp.

Het lijkt mij dat het begrip van de kwaliteit van het ontwerp en de redenen voor het "verval" de belangrijkste eigenschappen zijn voor elke programmeur. Zoals in de meeste andere gevallen, is het belangrijkste om het probleem te identificeren, en het zal een kwestie van technologie zijn om het op te lossen.

Definitie van "slecht ontwerp"

Als je besluit om op te scheppen over je code in het bijzijn van een collega-programmeur, zul je hoogstwaarschijnlijk belachelijk worden gemaakt als reactie: "Wie doet dit?", 'Waarom is het zo?' en "Ik zou dingen anders doen." Dit gebeurt heel vaak.

Alle mensen zijn verschillend, maar je schrijft nog steeds de code voor je collega-programmeurs, dus tijdens het ontwikkelen van elke functie heb je altijd een beoordelingsfase nodig wanneer andere mensen naar je code kijken.

Maar zelfs als veel dingen op verschillende manieren kunnen worden gedaan, is er een reeks criteria waar alle ontwikkelaars het over eens zijn. Elk stuk code dat aan zijn eisen voldoet, maar nog steeds een (of meer) kenmerken vertoont, is een slecht ontwerp.

Slecht ontwerp:

  • Moeilijk te veranderen omdat elke verandering te veel andere delen van het systeem beïnvloedt. ( Stijfheid , Stijfheid).
  • Wanneer er wijzigingen worden aangebracht, gaan andere delen van het systeem onverwacht kapot. ( Breekbaarheid , Breekbaarheid).
  • De code is moeilijk opnieuw te gebruiken in een andere toepassing omdat het te moeilijk is om deze uit de huidige toepassing te halen. ( Onbeweeglijkheid , Immobiliteit).

En het grappige is dat het bijna onmogelijk is om een ​​onderdeel van het systeem te vinden dat geen van deze kenmerken bevat (dat wil zeggen flexibel, betrouwbaar en herbruikbaar is), aan de eisen voldoet en tegelijkertijd slecht is ontworpen .

We kunnen deze drie kenmerken dus gebruiken om ondubbelzinnig te bepalen of een ontwerp 'slecht' of 'goed' is.

Oorzaken van "slecht ontwerp"

Wat maakt een ontwerp rigide, broos en onbeweeglijk? Starre onderlinge afhankelijkheid van modules.

Een ontwerp is rigide als het niet gemakkelijk kan worden gewijzigd. Deze rigiditeit is te wijten aan het feit dat een enkele wijziging in een stuk code in een geweven systeem resulteert in trapsgewijze veranderingen in afhankelijke modules. Dit gebeurt altijd wanneer één persoon aan de code werkt.

Dit bemoeilijkt meteen het hele commerciële ontwikkelproces: wanneer het aantal trapsgewijze wijzigingen niet kan worden voorspeld door de ontwerper of ontwikkelaar, is het onmogelijk om de impact van zo'n wijziging in te schatten. Daarom proberen ze dergelijke wijzigingen voor onbepaalde tijd uit te stellen.

En dit maakt op zijn beurt de kosten van verandering onvoorspelbaar. Geconfronteerd met dergelijke onzekerheid, aarzelen managers om veranderingen door te voeren, zodat het ontwerp officieel rigide wordt.

Op een gegeven moment passeert uw project de 'gebeurtenishorizon' en is het gedoemd om in het 'zwarte gat' van de rigide architectuur te vallen.

Fragiliteit is de neiging van een systeem om na een enkele wijziging op meerdere plaatsen kapot te gaan. Gewoonlijk doen zich nieuwe problemen voor op plaatsen die conceptueel geen verband houden met de plaats van verandering. Een dergelijke kwetsbaarheid ondermijnt het vertrouwen in het ontwerp en onderhoud van het systeem ernstig.

Dit was meestal het geval als er geen privémethodes waren. Het volstaat om alle methoden openbaar te maken, en je bent gedoemd tot de schijn van een fragiele architectuur. Inkapseling helpt om hiermee op microniveau om te gaan. Maar op macroniveau heb je een modulaire architectuur nodig.

Wanneer een project een fragiele architectuur heeft, kunnen de ontwikkelaars de kwaliteit van het product niet garanderen.

Eenvoudige wijzigingen in een deel van de applicatie leiden tot bugs in andere niet-gerelateerde delen. Het corrigeren van deze fouten leidt tot nog meer problemen en het escortproces verandert in een beroemde hond die zijn eigen staart achterna zit.

Het ontwerp is onbeweeglijk wanneer de noodzakelijke onderdelen van het systeem sterk verbonden zijn met andere ongewenste details. Te veel van hun eigen code, hun eigen unieke benaderingen en oplossingen.

Herinner je je de JUL-logger nog, waarvan de ontwikkelaars zonder goede reden hun eigen logging-niveaus bedachten? Dit is gewoon het geval.

Om een ​​ontwerper een idee te geven hoe gemakkelijk het is om een ​​bestaand ontwerp te hergebruiken, volstaat het om na te denken over hoe gemakkelijk het zal zijn om te gebruiken in een nieuwe toepassing.

Als het ontwerp nauw met elkaar verbonden is, zal deze ontwerper geschokt zijn door de hoeveelheid werk die nodig is om de vereiste onderdelen van het systeem te scheiden van de onnodige details. In de meeste gevallen is zo'n ontwerp niet herbruikbaar, omdat de kosten van het scheiden ervan opwegen tegen het vanaf nul ontwikkelen.

Relevantie

Alles verandert, maar alles blijft hetzelfde. (Chinees gezegde)

Hierboven zijn zeer goede vragen gesteld. Wat zijn de gevaren van fragiele en rigide systemen? Ja, omdat het proces van het managen van zo'n project onvoorspelbaar en oncontroleerbaar wordt. En de prijs is exorbitant.

Hoe kan een manager wel of niet het groene licht geven om een ​​functie toe te voegen als hij niet weet hoeveel tijd het daadwerkelijk gaat kosten? Hoe taken prioriteren als u de tijd en complexiteit van hun implementatie niet adequaat kunt inschatten?

En hoe kunnen ontwikkelaars dezelfde technische schuld afbetalen als we het willen betalen, en we kunnen niet begrijpen hoeveel we zullen harken totdat we harken?

Problemen met hergebruik of testen van code zijn ook zeer relevant. Unit-tests dienen niet alleen om enkele aannames over de te testen unit te testen, maar ook om de mate van samenhang te bepalen en kunnen dienen als indicator voor hergebruik.

Hier is een citaat van Bob Martin voor dit geval: "Om uw code opnieuw te gebruiken, moet u minder moeite doen om deze opnieuw te gebruiken dan de kosten van helemaal opnieuw ontwikkelen . " Anders zal niemand zich zelfs maar met deze kwestie bezighouden.

Het gebruik van ontwerpprincipes en -patronen dient één doel - om ontwerp goed te maken. Als het gebruik ervan u geen enkel voordeel oplevert (of vice versa, in strijd is met de principes van "goed ontwerp"), dan klopt er iets niet in uw serre en wordt de tool misschien voor andere doeleinden gebruikt.