[C#/OO] Ontwerp keuze, hoe netjes te maken?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Stel ik heb een aantal klassen, ik kom erachter dat ik het een en ander aan herhaling doe, dus ik wil code refactoren. Na wat onderzoek blijkt het enige dat steeds anders is, een query string is.
Joepie!
Ik heb dus een generieke basis klasse geschreven met een aantal methoden, zoiets:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// illustratief voorbeeld
public abstract ClassBase<T>
{
    public virtual T GetIets(int x)
    {
         // logica
     }

    public virtual List<T> GetNogMeer()
    {
        // logica
    }
}

// met nog eental concrete
public ConcreteClass : Classbase<ConcreteClass>
{
    
     public override ConcreteClass GetIets(int x)
     {
         // zorg dat de base de juist query string kan gebruiken  
         return base.GetIets(x);
     }

    public override List<ConcreteClass> GetNogMeer()
    {
        // zorg dat de base de juist query string kan gebruiken  
         return base.GetNogMeer();
    }
}


Welnu, ik ben tegen het volgende aangelopen, namelijk het gebrek aan een nette manier om de querystring bekend te maken aan de base class. Momenteel doe ik het als volgt:
Ik definieer, in de ClassBase, een property en in de methods overrides in de ConcreteClass roep ik eenvoudig de base aan. Zoiets als dit:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// illustratief voorbeeld
public abstract ClassBase<T>
{
    public abstract Type<T> Porp { get; }

    public string Prop{ get; set; }

    public virtual T GetIets(int x)
    {
         // doe iets met Prop 
         // Type<T> ding = Porp
         // verzameling = ding.doeIets
     }

    public virtual List<T> GetNogMeer()
    {
        // doe iets met Prop 
        // Type<T> ding = Porp
         // verzameling = ding.doeIets
    }
}

// met nog eental concrete
public ConcreteClass : Classbase<ConcreteClass>
{
    // in dit geval wel prima natuurlijk!
    public override Type<ConcreteClas> { get { return Ding; } }     

     public override ConcreteClass GetIets(int x)
     {
         // zorg dat de base de juist query string kan gebruiken 
         base.Prop = "Henk"; 
         return base.GetIets(x);
     }

    public override List<ConcreteClass> GetNogMeer()
    {
        // zorg dat de base de juist query string kan gebruiken  
        base.Prop = "Piet";
        return base.GetNogMeer();
    }
}
// in het echt gaat het om 2 properties en ik irriteer me er mateloos aan!


Het werkt verder prima, maar ik krijg er echt een vieze nasmaak van in m'n mond. Het voelt alsof het niet klopt. Heeft iemand misschien tips hoe ik dit netter zou kunnen oplossen? Er is ook nog een abstracte property in de base, die in de concrete override wordt, maar dat is iets wat voor heel die bewuste concrete klasse gelijk is en in zo'n geval vind ik het een mooie oplossing.
Aangezien die query string steeds het enige is dat varieert, denk ik dat ik er wel iets meer mee kan doen, maar het komt er niet echt uit zeg maar :P
Ik heb er overigens geen problemen de structuur grondig te wijzigen als dat nodig is ;)

[ Voor 12% gewijzigd door Verwijderd op 15-12-2010 23:45 ]


Acties:
  • 0 Henk 'm!

  • bomberboy
  • Registratie: Mei 2007
  • Laatst online: 02:47

bomberboy

BOEM!

Het is me niet helemaal duidelijk waarom je die get-methoden override in je ConcreteClass. Zoals je zelf al aangeeft is die implementatie eigenlijk identiek en is het enkel de waarde van die properties die anders zijn. Het lijkt me dan nuttiger dat je die properties gewoon in de constructor zet (van je ConcreteClass).

Strikt genomen kan je dat in jouw verhaal zoals je het hier gepost hebt zelf de ConcreteClasses helemaal weg laten en die properties meegeven in de constructor van je "ClassBase". Maar het kan in bepaalde gevallen inderdaad nuttig zijn dat te verbergen en gebruik te maken van een klassenhierarchie.

Kort samengevat, in de constructor van je ConcreteClass zet je de property in je ClassBase. (die property zetten kan dan door de setter aan te roepen of als argument in de constructor van je ClassBase uiteraard)

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Strikt genomen kan je dat in jouw verhaal zoals je het hier gepost hebt zelf de ConcreteClasses helemaal weg laten
Heb er nog even een kleine toevoeging aan gedaan. De ConcreteClasses hebben helaas nog meer te doen :)
Ze zorgen verderop voor nog wat generic magic :P
Kort samengevat, in de constructor van je ConcreteClass zet je de property in je ClassBase. (die property zetten kan dan door de setter aan te roepen of als argument in de constructor van je ClassBase uiteraard)
Dat betekent dan wel dat er voor elk van de verschillende methodes (en dus queries) een nieuwe property gemaakt moet worden in de ClassBase<T>. Opzich niet onoverkomelijk, maar of het een mooiere oplossing is? Het zou wel mooi zijn om van het overriden van die Get() dingen af te komen en het allemaal zo schoon mogelijk te houden.
Nu is er (voor de query strings) 1 property, die door elke methode anders gezet wordt, alleen de manier waarop vind ik lelijk. Helaas is er nog een property (een enum die voor een connectie staat), die per query anders kan zijn. Kan ik ze niet beiden encapsuleren in een interface op de een of andere manier, maar voor mn gevoel verplaats ik het probleem dan alleen maar.

Ik begin me steeds meer af te vragen of ik niet gewoon een enorme fout heb gemaakt of het gewoon moet laten rusten...

[ Voor 30% gewijzigd door Verwijderd op 16-12-2010 00:02 ]


  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
Verwijderd schreef op woensdag 15 december 2010 @ 23:08:
Stel ik heb een aantal klassen, ik kom erachter dat ik het een en ander aan herhaling doe, dus ik wil code refactoren. Na wat onderzoek blijkt het enige dat steeds anders is, een query string is.
Joepie!
Ik heb dus een generieke basis klasse geschreven met een aantal methoden, zoiets:
je code voorbeelden maakt het voor mij niet duidelijker. Maar zoals ik het begrijp het je een base class die heel veel doet, en een query aanmaakt, en een child class, die hetzelfde doet, maar een andere query aanmaakt.

Waarom dan niet zoiets:

C#:
1
2
3
4
5
6
7
8
public class BaseClass{
...
    protected virtual Query CreateQuery(...);
}

public class ChildClass : BaseClass{
    protected override Query CreateQuery(...);
}


Of denk ik nu te simpel, stel je je probleem te simpel voor in de eerste paragraaf?

~ Mijn prog blog!