De O in SOLID en code vervuiling

Pagina: 1
Acties:

Vraag


Acties:
  • +1 Henk 'm!

  • Kleerkast
  • Registratie: November 2017
  • Laatst online: 28-09-2023
Ik verdiep me nu al een tijdje in The SOLID Principles.
- Single Responsibility
- Open for Extension, closed for modification
- Liskov Substitution principle
- Interface Segregation
- Dependency Injection

Nu loop ik alleen een beetje vast bij de O.

Op deze site https://www.baeldung.com/solid-principles word de O als volgt uitgelegd:
de klasse 'Guitar' word extended omdat er een 'flame-top' klasse word toegevoegd.
Maar als je voor deze 'features' allemaal een nieuwe klasse gaat toevoegen, word je code dan niet een grote zooi van kleine klasses, waarvan je ze eigenlijk in de base class kon doen?

Het voorbeeld

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Guitar {
 
    private String make;
    private String model;
    private int volume;
 
    //Constructors, getters & setters
}

public class SuperCoolGuitarWithFlames extends Guitar {
 
    private String flameColor;
 
    //constructor, getters + setters
}


Maar wat nou als ik bijvoorbeeld andere pickups wil in deze gitaar? of misschien wel snaren van een basgitaar erop wil zetten?

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Pickups extends Guitar {
 
    private String brand;
    private Enum type;
 
    //constructor, getters + setters
}

public class BassGuitarStrings extends Guitar {
 
    private String brand;
    private int gauge;
 
    //constructor, getters + setters
}


Kan dit dan niet beter?
Java:
1
2
3
4
5
6
7
8
9
10
11
public class Guitar {
 
    private String make;
    private String model;
    private int volume;
    private enum StringType;
    private string finishType;
    private enum PickupType;

    //Constructors, getters & setters
}

[ Voor 8% gewijzigd door Kleerkast op 05-09-2019 12:11 ]

Beste antwoord (via Kleerkast op 05-09-2019 13:22)


  • wuppie007
  • Registratie: Augustus 2011
  • Laatst online: 12:41
Interresant topic, maar ik denk dat iedere ontwikkelaar wel eens worstelt met de toepassing van deze principes.

Maar met het open/closed principe denk ik dat ze meer bedoelen dat je bestaande code niet teveel moet aanpassen (tenzij het bugs zijn natuurlijk) "In doing so, we stop ourselves from modifying existing code and causing potential new bugs in an otherwise happy application."

Alle reacties


Acties:
  • +1 Henk 'm!

Verwijderd

Een pickup en een snaar is niet een subklasse van Gitaar. Een Gitaar heeft wel een Pickup en een Snaar. Dus niet is-a, maar has-a.

Java:
1
2
3
4
5
6
7
8
9
10
public class Guitar {
 
    private String make;
    private String model;
    private int volume;
    private Pickup pickup;
    private GuitarStrings strings;
 
    //Constructors, getters & setters
}

Acties:
  • +1 Henk 'm!

  • mcDavid
  • Registratie: April 2008
  • Laatst online: 02-10 08:45
ligt allemaal een beetje aan de use-case. Er wordt een heel basic voorbeeld aangehaald om de principes duidelijk te maken. Als jij een dusdanig compacte class hebt, met alleen wat properties, is het waarschijnlijk idd onzin om die op te delen in verschillende subclasses.
Als je echter wat businesslogica toe gaat voegen, die ook nog eens verschillend is voor verschillende usecases... dan wordt het al snel een ander verhaal.

[ Voor 3% gewijzigd door mcDavid op 05-09-2019 12:19 ]


  • biomass
  • Registratie: Augustus 2004
  • Laatst online: 19:32
Volgens mij heb je wel door dat het een heel matig voorbeeld is. Door zoals @Euler212 een compositie te maken met class member variabelen met een bepaald doel, kun je zelf sturen welk gedrag in je class vast zou moeten zijn.

Acties:
  • +1 Henk 'm!

  • Kleerkast
  • Registratie: November 2017
  • Laatst online: 28-09-2023
Verwijderd schreef op donderdag 5 september 2019 @ 12:18:
Een pickup en een snaar is niet een subklasse van Gitaar. Een Gitaar heeft wel een Pickup en een Snaar. Dus niet is-a, maar has-a.

Java:
1
2
3
4
5
6
7
8
9
10
public class Guitar {
 
    private String make;
    private String model;
    private int volume;
    private Pickup pickup;
    private GuitarStrings strings;
 
    //Constructors, getters & setters
}
oh haha, ik dacht een beetje te moeilijk.

Het is inderdaad wel logisch om dit te kunnen doen:
Java:
1
2
SuperCoolGuitarWithFlames guitar = new SuperCoolGuitarWithFlames();
guitar.Color = red;



i.p.v

Java:
1
2
Guitar guitar = new Guitar();
guitar.top = flame;

o.i.d

Acties:
  • +1 Henk 'm!

  • TweakerNummer
  • Registratie: September 2001
  • Niet online
Guitar guitar = new Guitar(new FlameSkin());

FlameSkin extends Skin

Skin werkt normaal met 1 kleur (rood, groen, blauw), maar FlameSkin is een speciale skin. Overigens is dat ook nog een slecht voorbeeld. Een Skin baseclass met SingleColorSkin als uitgangspunt is beter, waarbij een GradientColorSkin als extended class fijner is.

[ Voor 34% gewijzigd door TweakerNummer op 05-09-2019 12:33 ]


  • Kleerkast
  • Registratie: November 2017
  • Laatst online: 28-09-2023
biomass schreef op donderdag 5 september 2019 @ 12:25:
Volgens mij heb je wel door dat het een heel matig voorbeeld is. Door zoals @Euler212 een compositie te maken met class member variabelen met een bepaald doel, kun je zelf sturen welk gedrag in je class vast zou moeten zijn.
Ja zoiets dacht ik al een beetje.
Ik denk nu ook dat de SOLID principes niet erg gericht zijn op kleinschalige projecten, maar merendeels op projecten met meerdere mensen

  • Stoelpoot
  • Registratie: September 2012
  • Niet online
TweakerNummer schreef op donderdag 5 september 2019 @ 12:29:
Guitar guitar = new Guitar(new FlameSkin());

FlameSkin extends Skin

Skin werkt normaal met 1 kleur (rood, groen, blauw), maar FlameSkin is een speciale skin.
Dan denk ik eerder dat Skin werkt met het patroon, en dat een Skin met 1 kleur een SolidSkin zou zijn. Dan kan je ook een Skin met meerdere kleuren gebruiken.

Acties:
  • +1 Henk 'm!

  • Mavamaarten
  • Registratie: September 2009
  • Laatst online: 19:55

Mavamaarten

Omdat het kan!

Kleerkast schreef op donderdag 5 september 2019 @ 12:29:
[...]


Ja zoiets dacht ik al een beetje.
Ik denk nu ook dat de SOLID principes niet erg gericht zijn op kleinschalige projecten, maar merendeels op projecten met meerdere mensen
Wrong :)
Goed programmeren is niet enkel nodig op grote projecten. Ook bij kleine projectjes van jezelf is een goede stijl van belang. Het maakt het verschil tussen "ik verveel me, ik kan nog effe verder werken aan X" en "hmm laat ook maar, ik kan er niet direct meer aan uit en als ik Y wil doen moet ik het eigenlijk vanaf nul terug opnieuw schrijven".

Je moet SOLID niet zien als een reeks regeltjes die elke programmeur tot op de letter volgt. Naarmate je vordert in je programmeerskills zul je zien dat je een heel aantal patronen gaat volgen. Die patronen maken je leven gewoon makkelijker. Je schrijft snel even een interface voor iets wat je later gaat bouwen, en later implementeer je die. En per ongeluk heb je je daarmee aan de regels van SOLID gehouden.

Android developer & dürüm-liefhebber


  • biomass
  • Registratie: Augustus 2004
  • Laatst online: 19:32
Je kunt prima in je eentje aan SOLID vast houden hoor! Als je je niet aan SOLID houdt kun je in een groep programmeurs wel commentaar verwachten, als de constructies wat bijzonder worden. ;)

  • TweakerNummer
  • Registratie: September 2001
  • Niet online
Stoelpoot schreef op donderdag 5 september 2019 @ 12:33:
[...]


Dan denk ik eerder dat Skin werkt met het patroon, en dat een Skin met 1 kleur een SolidSkin zou zijn. Dan kan je ook een Skin met meerdere kleuren gebruiken.
KISS & https://hackernoon.com/hn...zS-UkYtNOgzPvpkHGwRbQ.png

Acties:
  • Beste antwoord
  • 0 Henk 'm!

  • wuppie007
  • Registratie: Augustus 2011
  • Laatst online: 12:41
Interresant topic, maar ik denk dat iedere ontwikkelaar wel eens worstelt met de toepassing van deze principes.

Maar met het open/closed principe denk ik dat ze meer bedoelen dat je bestaande code niet teveel moet aanpassen (tenzij het bugs zijn natuurlijk) "In doing so, we stop ourselves from modifying existing code and causing potential new bugs in an otherwise happy application."

Verwijderd

Bedoel je misschien niet dit?

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Guitar {
 
    private String brand;
    private String model;
    private Integer strings;
    private Boolean electric;
 
    //Constructors, getters & setters
}

public class ElectricGuitar extends Guitar {
    
    private String pickups;
    private Boolean wammy;
 
    //constructor, getters + setters
}

public class AcousticGuitar extends Guitar {
    private String acousticType; // Can be classical, flamenco, etc
    
    //constructor, getters + setters
}

[ Voor 6% gewijzigd door Verwijderd op 05-09-2019 14:39 ]


  • com2,1ghz
  • Registratie: Oktober 2004
  • Laatst online: 00:57
wuppie007 schreef op donderdag 5 september 2019 @ 13:15:
Interresant topic, maar ik denk dat iedere ontwikkelaar wel eens worstelt met de toepassing van deze principes.

Maar met het open/closed principe denk ik dat ze meer bedoelen dat je bestaande code niet teveel moet aanpassen (tenzij het bugs zijn natuurlijk) "In doing so, we stop ourselves from modifying existing code and causing potential new bugs in an otherwise happy application."
Incorrect. Je hoort altijd vrij te zijn in het aanpassen van code. Indien dit niet mogelijk is dan is je code niet (goed) getest.

Het gaat er om dat je code zodanig moet ontwerpen dat het open is voor uitbreiding en gesloten voor aanpassing.

Je staat niet te wachten op:
code:
1
2
3
4
5
6
7
public void play() {
  if (guitar instanceof SuperCoolGuitarWithFlames) {
    //do iets met SuperCoolGuitarWithFlames
  } else {
   //doe wat anders
  }
}

...want als iemand een andere implementatie toevoegt van Guitar dan ben je genoodzaakt de bovenstaande play() method aan te passen.

Nou is dit een zwak voorbeeld op Baeldung, maar inheritance zou ik vermijden als het niet nodig is :)

  • Kleerkast
  • Registratie: November 2017
  • Laatst online: 28-09-2023
com2,1ghz schreef op donderdag 5 september 2019 @ 15:14:
[...]

Incorrect. Je hoort altijd vrij te zijn in het aanpassen van code. Indien dit niet mogelijk is dan is je code niet (goed) getest.

Het gaat er om dat je code zodanig moet ontwerpen dat het open is voor uitbreiding en gesloten voor aanpassing.

Je staat niet te wachten op:
code:
1
2
3
4
5
6
7
public void play() {
  if (guitar instanceof SuperCoolGuitarWithFlames) {
    //do iets met SuperCoolGuitarWithFlames
  } else {
   //doe wat anders
  }
}

...want als iemand een andere implementatie toevoegt van Guitar dan ben je genoodzaakt de bovenstaande play() method aan te passen.

Nou is dit een zwak voorbeeld op Baeldung, maar inheritance zou ik vermijden als het niet nodig is :)
Hij is niet incorrect volgens mij:

https://stackify.com/solid-design-open-closed-principle/
A class is closed, since it may be compiled, stored in a library, baselined, and used by client classes. But it is also open, since any new class may use it as parent, adding new features. When a descendant class is defined, there is no need to change the original or to disturb its clients.”
En dat voorbeeld dat je gaf.
code:
1
2
3
4
5
6
7
public void play() {
  if (guitar instanceof SuperCoolGuitarWithFlames) {
    //do iets met SuperCoolGuitarWithFlames
  } else {
   //doe wat anders
  }
}


Het voorbeeld wat ik als eerste had gequote is slecht. Want als we toch alles gaan deriven van Guitar, kan het het beste een interface worden (denk ik).

code:
1
2
3
4
5
6
7
8
9
interface Guitar
{
    public void Play();
}

public void play(Guitar _guitar)
{
    _guitar.Play();
}

  • com2,1ghz
  • Registratie: Oktober 2004
  • Laatst online: 00:57
Dat bedoel ik ook. Je code moet zodanig ontworpen zijn dat het niet nodig is om een stuk code aan te passen als je het uitbreid. Of die code nou gecompiled is of niet. Echter is het geen geldig argument code niet aan te mogen raken omdat er mogelijks bugs kunnen ontstaan. Dan kan je je code quality in tijfel trekken.

Afhankelijk van je use case zou je mogelijk een interface kunnen gebruiken. Daar kan ik met deze informatie geen uitspraak over doen. Het gebruik van interfaces valt weer onder Liskov subtitution en Interface Segregation.
Prefer composition over inheritance. Inheritance is niet fout, maar wordt vaak misbruikt.

[ Voor 3% gewijzigd door com2,1ghz op 05-09-2019 15:55 ]


  • wuppie007
  • Registratie: Augustus 2011
  • Laatst online: 12:41
Interface kan inderdaad een oplossing zijn in dit geval. Als je dit soort dingen interessant vind, dan kan ik je ook nog aanbevelen om je te verdiepen in software design patterns.

In dit voorbeeld kan misschien het 'strategy pattern' een oplossing bieden. Om verschillende eigenschappen aan een object 'te hangen'.


Zelf vind ik dit een hele interessante tak van software ontwikkeling: hoe bouw je je software op, hoe hou je het simpel, welke uitbreidingen worden misschien voorzien in de toekomst?

Ik zie deze principes en patronen meer als tools in je gereedschapskist. Op zichzelf zijn ze allemaal handig, maar niet altijd (handig) toepasbaar

  • Kleerkast
  • Registratie: November 2017
  • Laatst online: 28-09-2023
Zal ik zeker gaan doen!
Binnenkort maar even Clean Code bestellen van Uncle Bob ;)

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
@Kleerkast OO design principles zijn een groot en complex onderwerp die je niet kunt samenvatten in een Baeldung post van 3 pagina's. Het probleem van de meeste van dit soort "hoe doe je OO" voorbeelden is dat ze erg simplistisch zijn (en in het geval van Baeldung ook vaak uitgelegd worden door mensen die ze niet begrijpen).

Het belangrijkste deel van het Open/Closed princiepe is dat je mensen niet in de interne werking van je classes laat frutten. Laat ze, indien nodig, maar een class extenden. Maar door 'frutten' maak je het stuk. Het heeft dan ook niet zo heel veel zin te focussen op het "extenden" deel van het verhaal; dat is compleet afhankelijk van het design. En daar komt ook het composition over inheritance verhaal om de hoek kijken (wat overigens door extreem veel developers ook weer verkeerd uitgelegd wordt).

Zoals anderen al uitlegden is inheritance een "is a" relatie. Dingen als een kleurtje, snaren e.d. zijn geen "is a" maar "has a" relaties; dat zijn dus gewoon stukjes informatie.
wuppie007 schreef op donderdag 5 september 2019 @ 13:15:
Maar met het open/closed principe denk ik dat ze meer bedoelen dat je bestaande code niet teveel moet aanpassen (tenzij het bugs zijn natuurlijk) "In doing so, we stop ourselves from modifying existing code and causing potential new bugs in an otherwise happy application."
Bizar dat dit als "beste antwoord" gemarkeerd is, dit is gewoon compleet fout. SOLID gaat over hoe je OO software designed en heeft niks te maken met al dan niet bestaande code verbouwen.

[ Voor 48% gewijzigd door Hydra op 05-09-2019 16:20 ]

https://niels.nu


  • wuppie007
  • Registratie: Augustus 2011
  • Laatst online: 12:41
Hydra schreef op donderdag 5 september 2019 @ 16:15:

[...]


Bizar dat dit als "beste antwoord" gemarkeerd is, dit is gewoon compleet fout. SOLID gaat over hoe je OO software designed en heeft niks te maken met al dan niet bestaande code verbouwen.
Ik citeer slechts de website waarnaar de topic starter verwijst, omdat ik dacht dat hij de uitleg van de site had 'gemist'.

Maar, "SOLID gaat over hoe je OO software designed en heeft niks te maken met al dan niet bestaande code verbouwen"

Dit heeft toch alles met elkaar te maken? Een 'slecht' design kan het verbouwen/onderhouden van code in de toekomst behoorlijk beïnvloeden.

Op het gebied van code design, ik merk zelf dat het me veel brengt om veel theorieën/voorbeelden etc te bestuderen en wie weet komt het in de toekomst ooit van pas ;)
Pagina: 1