verantwoordelijkheden van een class

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • martijngr85
  • Registratie: Maart 2009
  • Laatst online: 05-08 10:32
Beste mensen,

Ik worstel een beetje met de architectuur van mijn applicatie. Dit probleem heb ik eigenlijk altijd, maar vind dat het nu tijd is om knopen door te hakken :)

Net zoals nu bijvoorbeeld heb ik een User class. Methoden die te maken hebben met users zijn:

Login(username, password)
GetUserById()
GetUsersByGroupId()
AddUser()
EditUser()
DeleteUser()

Het punt is dat ik altijd twijfel waar ik deze methoden moet plaatsen. In eerste instantie zou je zeggen plaats ze in de user class. Maar deze class is niet verantwoordelijk voor het ophalen voor alle users die in een bepaalde groep zitten. Daarbij mag deze class ook geen data ophalen uit de database. Of wel? Als dit niet het geval is, komt er dus een extra class bij: UserManager(/UserData/UserFactory net erna hoe je het noemen wil). Deze class mag wel data ophalen en is niet verantwoordelijk voor één user, dus mag die een lijst teruggeven met alle users. Alleen vraag ik me af: is deze beredenering correct?

Ik heb dus een beetje moeite met de verantwoordelijkheden van een class: wat mag hij wel en wat mag hij niet / waar plaats ik welke methode en waarom?

Ik hoop dat jullie mij kunnen helpen en tips hebben om voortaan zulk soort problemen op te lossen.

Alvast bedankt.

Martijn

Acties:
  • 0 Henk 'm!

  • rvanlooijen
  • Registratie: Oktober 2001
  • Laatst online: 21-06-2021
Sja, beiden wordt gedaan. Persoonlijk ben ik het met jouw beredenering eens, puur gezien is een 'User' natuurlijk een ding wat alleen maar iets weet van zichzelf en misschien wat dingen kan. Dan krijg je inderdaad een manager constructie om dingen te doen die metadata van User regelt, dus (bewerkingen op) lijsten van users maar ook het maken en verwijderen van een bepaalde User. Deze keuze wordt ook weer anders wanneer je gebruik gaat maken van persistentie frameworks/EJB's, aangezien de keuze dan niet meer bij jou ligt.

Deze oplossing is zelfs noodzakelijk als je dingen als transacties op een zinvolle manier wilt gaan gebruiken, maar daar heb je vermoedelijk op dit moment nog niet mee te maken.

//edit: Als je serieus wilt nadenken over hoe de architectuur van een applicatie in elkaar zit is het een goed plan om eens te gaan kijken naar allerhande design patterns zoals/en MVC. Om te beginnen kan ik je de boeken Head First Design Patterns en Head First Java sterk aanraden.

[ Voor 16% gewijzigd door rvanlooijen op 16-06-2009 09:46 . Reden: toevoeging ]


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
Zoals reeds gezegd:
beiden worden gedaan.

Ik moet zeggen dat ik zeker geen fan ben van de eerste oplossing (ActiveRecord pattern). Voor de Login method zou je nog iets kunnen zeggen (al ben ik toch van mening dat deze niet in de User class thuishoort), maar de overige methods horen er imho zeker niet in thuis.

Ik ben eerder voor de manier waarop je de CRUD & andere data-store related methods in een repository gaat gaan herbergen (repository aanpak).

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

Verwijderd

Klein tipje: Laat niet de naam van de class terugkomen in de functienamen, dit is dubbelop en zorgt voor rare effecten bij overerving ed.

Acties:
  • 0 Henk 'm!

  • martijngr85
  • Registratie: Maart 2009
  • Laatst online: 05-08 10:32
Bedankt voor de snelle reacties.

@caesartje: Het boek Head First Design patterns heb ik reeds in bezit. Alleen heb ik nog niet echt een patroon kunnen ontdekken waar dit ter sprake komt (of ik heb er overheen gelezen).

Dus jullie zeggen, zodra er een verbinding met de database bij komt kijken, herberg dit dan in een Manager class. Overige methods die bij user horen gewoon in de user class stoppen.

@TRRoads: Thnx voor de tip :)

Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
Ik zou als ik jou was eens gaan kijken naar wat MVC principes. Dan krijg je een heldere structuur als volgt:
  • UserController: voert allerlei regelzaken uit, zoals inloggen en uitloggen
  • UserModel: is de representatie van de user (dus bevat een id, username etc). Het is eigenlijk een zogenaamd domein model. Naast het domain model kan je nog twee andere klassen maken:
    • Data mapper: deze mapt de data van de database aan je model. Dus daarin zitten eigenlijk de find() en fetchAll() functies.
    • Table data gateway: een klasse die de tabel representeert waarin je modellen staan
  • View: de template van je systeem, die bepaalt hoe alles eruit komt te zien
Het klinkt om te beginnen erg ingewikkeld. Maar als je er eenmaal aan gewend bent wil je eigenlijk niets anders meer ;)

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
mithras schreef op dinsdag 16 juni 2009 @ 10:01:
Ik zou als ik jou was eens gaan kijken naar wat MVC principes. Dan krijg je een heldere structuur als volgt:
  • UserController: voert allerlei regelzaken uit, zoals inloggen en uitloggen
  • UserModel: is de representatie van de user (dus bevat een id, username etc). Het is eigenlijk een zogenaamd domein model. Naast het domain model kan je nog twee andere klassen maken:
    • Data mapper: deze mapt de data van de database aan je model. Dus daarin zitten eigenlijk de find() en fetchAll() functies.
    • Table data gateway: een klasse die de tabel representeert waarin je modellen staan
  • View: de template van je systeem, die bepaalt hoe alles eruit komt te zien
Het klinkt om te beginnen erg ingewikkeld. Maar als je er eenmaal aan gewend bent wil je eigenlijk niets anders meer ;)
MVC heeft hier helemaal niks mee te maken :? ....

MVC is een manier om je model, controllers & UI te gaan scheiden. De topicstart gaat over een vraag die volledig met het 'model' te maken heeft.
(Ja, repository hoort voor mij bij het model / domain). :)

@TS: je kan een repository zien als een 'data-store' / manier om aan je data-store te geraken. Het is dus een abstractie van de manier waarop je data opgeslagen wordt. De repository gaat er dus bv voor zorgen dat je de nodige records uit je database haalt, en een User object gaan teruggeven.

(Ik heb trouwens in m'n eerste reply een aantal sleutelwoorden gestopt waar je wel eens zou kunnen op googlen .... ;) ).

[ Voor 3% gewijzigd door whoami op 16-06-2009 10:05 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
whoami schreef op dinsdag 16 juni 2009 @ 10:04:
[...]
MVC heeft hier helemaal niks mee te maken :? ....

MVC is een manier om je model, controllers & UI te gaan scheiden. De topicstart gaat over een vraag die volledig met het 'model' te maken heeft.
(Ja, repository hoort voor mij bij het model / domain). :)
Waarom zou een login actie bij het model horen? Dat lijkt me nu niet iets voor een model ;)

Omdat er verschillende acties in zijn lijstje staan heb ik het idee dat bij de TS het scheiden van principes nog niet helemaal duidelijk is. Ook het plaatsen van CRUD acties in je domain model vind ik niet helemaal netjes, omdat het meer een data mapper taak is (afaik).

Ik vond het domain model / data mapper / table data gateway rijtje makkelijker te onthouden als je eerst iets weet over mvc. Vandaar dat ik het ook uitleg in een adem, maar het heeft inderdaad niet veel met het probleem van TS te maken (hoewel je nog wel de login uit je model moet halen imho).

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
mithras schreef op dinsdag 16 juni 2009 @ 10:12:
[...]
Waarom zou een login actie bij het model horen? Dat lijkt me nu niet iets voor een model ;)
Wat is het dan wel ? Een login is een actie die een gebruiker oplevert (of juist niet). Hoort volgens mij bij de repository, en repository is een first-class model citizen.
Omdat er verschillende acties in zijn lijstje staan heb ik het idee dat bij de TS het scheiden van principes nog niet helemaal duidelijk is. Ook het plaatsen van CRUD acties in je domain model vind ik niet helemaal netjes, omdat het meer een data mapper taak is (afaik).
Repository gebruikt een data-mapper in sommige gevallen. De implementatie van de repository stop ik meestal niet bij het model zelf, maar de interface van m'n repository wel. Die zijn nl. onlosmakelijk met het model verbonden.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • martijngr85
  • Registratie: Maart 2009
  • Laatst online: 05-08 10:32
Ik ga me eens verdiepen inderdaad in het een en ander. Ik heb al wel eens iets gedaan met MVC alleen heb ik daarbij nog steeds te maken het met vaststellen van de verantwoordelijkheden (welke method zet ik in welke class?)

Overigens, bijvoorbeeld de method GetUserById() wat zouden jullie hem geven als return value? Een boolean om aan te geven dat het gelukt is om de user op te halen? (en dan vervolgens via een property de user daadwerkelijk ophalen) Of gewoon null by niet gelukt en een gevuld object bij gelukt? En hoe zouden jullie een exception afvangen?

Beetje veel dingen, ik weet het, maar zoals ik al eerder aangaf.. Ik worstel een beetje met wat architectuur dingetjes en wil nu wat knopen doorhakken :)

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
martijngr85 schreef op dinsdag 16 juni 2009 @ 10:21:
Overigens, bijvoorbeeld de method GetUserById() wat zouden jullie hem geven als return value? Een boolean om aan te geven dat het gelukt is om de user op te halen? (en dan vervolgens via een property de user daadwerkelijk ophalen) Of gewoon null by niet gelukt en een gevuld object bij gelukt? En hoe zouden jullie een exception afvangen?
De naam zegt het toch zelf ? GetUser
Een User object dus.
En als er geen User bestaat met dat Id, kan je kiezen wat je doet: ofwel gooi je een exceptie, ofwel return je NULL.
(Ik zou voor het laatste opteren).

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
whoami schreef op dinsdag 16 juni 2009 @ 10:17:
[...]

Wat is het dan wel ? Een login is een actie die een gebruiker oplevert (of juist niet). Hoort volgens mij bij de repository, en repository is een first-class model citizen.
Daar zijn ws nog wel verschillende opvattingen over. Ik doe het altijd in mijn controller, maar dat zal vast te betwisten zijn. Ik hou me tegenwoordig ook niet echt meer met de diepste onderdelen bezig: met een framework roep ik (wel in mijn controller) een authenticate actie aan en dan is het klaar. Wat er verder intern gebeurt weet ik dus eigenlijk ook niet precies :P
martijngr85 schreef op dinsdag 16 juni 2009 @ 10:21:
Ik ga me eens verdiepen inderdaad in het een en ander. Ik heb al wel eens iets gedaan met MVC alleen heb ik daarbij nog steeds te maken het met vaststellen van de verantwoordelijkheden (welke method zet ik in welke class?)

Overigens, bijvoorbeeld de method GetUserById() wat zouden jullie hem geven als return value? Een boolean om aan te geven dat het gelukt is om de user op te halen? (en dan vervolgens via een property de user daadwerkelijk ophalen) Of gewoon null by niet gelukt en een gevuld object bij gelukt? En hoe zouden jullie een exception afvangen?

Beetje veel dingen, ik weet het, maar zoals ik al eerder aangaf.. Ik worstel een beetje met wat architectuur dingetjes en wil nu wat knopen doorhakken :)
Nou, je wil een user hebben, dus verwacht je ook een user te retourneren :)

Als voorbeeldje misschien wat code. Ik werk eigenlijk alleen met php en dat is misschien niet de beste in dit soort paradigma's, maar het is denk ik wel te begrijpen:
PHP:
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
class userModel
{
  protected $_id;
  protected $_name;
  protected $_password;

  public function find($id)
  {
    return $this->getMapper()->find($this, $id);
  }

  public function getMapper()
  {
    if (null === $this->_mapper) {
      $this->_mapper = new userMapper;
    }
    return $this->_mapper;
  }
}

class userMapper
{
  public function find(userModel $user, $id)
  {
    $result = $this->getDbTable()->doSomeQueryWith($id);
    if ($result->isCorrect()) {
      $user->setId($result->id)
           ->setName($result->name)
           ->setPassword($result->password);
    }
    return $user;
  }
}

class userController
{
  public function someAction()
  {
    $user = new userModel;
    $user = $user->find($id);
  }
}

Acties:
  • 0 Henk 'm!

  • martijngr85
  • Registratie: Maart 2009
  • Laatst online: 05-08 10:32
Jij zet dus de find methode in je User class, maar de daadwerkelijke implementatie in de UserMapper class. Dit is weer een ander benadering dan de Find in de UserManager class te zetten. Ik neem aan dat dit ook weer voor leuke discussie kan zorgen? Beetje hetzelfde als de Login methode...

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
martijngr85 schreef op dinsdag 16 juni 2009 @ 10:44:
Jij zet dus de find methode in je User class, maar de daadwerkelijke implementatie in de UserMapper class. Dit is weer een ander benadering dan de Find in de UserManager class te zetten. Ik neem aan dat dit ook weer voor leuke discussie kan zorgen? Beetje hetzelfde als de Login methode...
Ik niet (als je het op mij had ... ).

Ik doe het zo:

code:
1
2
3
public class User
{
}


code:
1
2
3
4
5
6
7
public class UserRepository : IUserRepository
{
   public User Find( .... )
   {
       // implementatie om User te zoeken.
   }
}

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • martijngr85
  • Registratie: Maart 2009
  • Laatst online: 05-08 10:32
Ja precies, jij pakt het anders aan dan whoami. Waarom maak je eigenlijk gebruik van een interface? Is dat niet overbodig?

Acties:
  • 0 Henk 'm!

  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 10-09 15:12

Nick_S

++?????++ Out of Cheese Error

whoami schreef op dinsdag 16 juni 2009 @ 10:23:
[...]
De naam zegt het toch zelf ? GetUser
Een User object dus.
En als er geen User bestaat met dat Id, kan je kiezen wat je doet: ofwel gooi je een exceptie, ofwel return je NULL.
(Ik zou voor het laatste opteren).
Ik niet. Ik begin steeds meer een hekel aan NULL te krijgen. ;) Alle if constructies om null checks te doen zijn in eigen code bijna altijd overbodig.

Als je een user opvraagt aan de hand van zijn ID verwacht je dat hij er is. (Je verzint, neem ik aan, geen ID's) Is deze er dus niet, is dat in mijn ogen een exceptie.

Als je de users d.m.v. hun achternaam wil ophalen is dat een set (geen dubbele) van users. Deze collectie kan ook nooit NULL zijn, het kan wel een lege collectie zijn. Aangezien het geen zin heeft om hier elementen uit weg te gooien, aangezien je daar een deleteUser voor hebt, is het ook nog een immutable collection.

[ Voor 78% gewijzigd door Nick_S op 16-06-2009 11:01 ]

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
Nick_S schreef op dinsdag 16 juni 2009 @ 10:54:
[...]

Ik niet. Ik begin steeds meer een hekel aan NULL te krijgen. ;) Alle if constructies om null checks te doen zijn in eigen code bijna altijd overbodig.

Als je een user opvraagt aan de hand van zijn ID verwacht je dat hij er is. (Je verzint, neem ik aan, geen ID's) Is deze er dus niet, is dat in mijn ogen een exceptie.
Tja, idd het kan vervelend zijn om iedere keer op null te moeten checken. Misschien is er idd iets voor te zeggen om een exceptie te gooien als je een niet bestaande primary identifier opgeeft ....
Als je de users d.m.v. hun achternaam wil ophalen is dat een set (geen dubbele) van users. Deze collectie kan ook nooit NULL zijn, het kan wel een lege collectie zijn. Aangezien het geen zin heeft om hier elementen uit weg te gooien, aangezien je daar een deleteUser voor hebt, is het ook nog een immutable collection.
Daar ben ik het volledig mee eens.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
martijngr85 schreef op dinsdag 16 juni 2009 @ 10:53:
Ja precies, jij pakt het anders aan dan whoami. Waarom maak je eigenlijk gebruik van een interface? Is dat niet overbodig?
Neen.
MIjn IUserRepository hoort bij m'n model; zit in dezelfde assembly/dll als mijn User class. Ik heb in sommige gevallen classes die methods hebben die een repository als argument hebben. Daar definieer ik dan dat ze een IxxxRepository meekrijgen.
Daarnaast heb ik ook een aantal implementaties van die repository-interfaces: nl. één 'echte' repository, waarbij ik NHibernate gebruik als data-mapper, en ik heb dan ook een implementatie die ik gebruik bij het unit-testen (die dus helemaal geen DB benaderd)

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 12-09 10:54

Janoz

Moderator Devschuur®

!litemod

Het schermt je af van de implementatie. Je kunt nu simpel meerdere implementaties van een user repository gebruiken. Dat klinkt misschien als iets dat je nooit nodig hebt, maar zelfs al bij het unittesten is het handig wanneer je een andere implementatie kunt gebruiken.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 10-09 15:12

Nick_S

++?????++ Out of Cheese Error

Ja precies, jij pakt het anders aan dan whoami. Waarom maak je eigenlijk gebruik van een interface? Is dat niet overbodig?
Gebruik maken van een interface is nooit overbodig. ;) Het vergemakkelijkt het gebruik van Dependency Injection frameworks en Inversion of Control. Gooi nooit in 1 klasse zowel object creatie als object gebruik.

Dus niet:
Java:
1
2
3
4
5
6
7
8
public class UserService {
    private UserRepository userRepository = new UserRepository();

    public doeIetsMetUsers() {
          Set<User> users = userRepository.getAllUsers();
          //Doe iets met users
    }
}

Maar:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
public class UserServiceImplementation implements UserService {
     private UserRepository userRepository;

     public UserServiceImplementation(UserRepository userRepository) {
         this.userRepository = userRepository;
     }

     @Override
     public doeIetsMetUsers() {
          Set<User> users = userRepository.getAllUsers();
          //Doe iets met users
     }


Ook vergemakkelijken interfaces het maken van unit tests, aangezien je dan mockobjecten kan gebruiken. Dat kan in het eerste voorbeeld ook niet, aangezien je in je klasse de instantie aanmaakt, ipv. dit over te laten aan een externe partij.

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
whoami schreef op dinsdag 16 juni 2009 @ 09:48:
Zoals reeds gezegd:
beiden worden gedaan.
Wat niet wil zeggen dan beiden goed zijn ;)

Ik ben zelf een groot voorstander van een bean structuur waarbij domme beans (users, items) aangeleverd / afgehandeld worden door factories. Het is voornamelijk een persoonlijke voorkeur, maar ik vind niet dat een user object hoort te weten waar 'ie vandaan komt. De kennis van het benaderen van een databron zou bij zijn concrete factory (huhu) moeten liggen.

https://niels.nu


Acties:
  • 0 Henk 'm!

Verwijderd

martijngr85 schreef op dinsdag 16 juni 2009 @ 10:53:
Ja precies, jij pakt het anders aan dan whoami. Waarom maak je eigenlijk gebruik van een interface? Is dat niet overbodig?
Mocht je ooit in de toekomst naar bijvoorbeeld oracle overstappen hoef je alleen de nieuwe oracle implementatie te maken en je model hoef je verder niet aan te passen omdat de interface voor zowel mysql en oracle gelijk is. De achterliggende code alleen niet.

En in plaats van iets in je applicatie te vervangen, breid je hem uit en kan je zonder enige moeite ook weer terug naar mysql.

Verder vind ik dit ook altijd een heel lastig punt. Vooral met databases en autoincrements. Maak je eerst het object aan en voeg je hem daarna in de database toe of voeg je hem eerst in de database toe en verwerk je hem eerst in je model.
Als je hem eerst in de database zet moet je daarna het object uit de database halen, wat ik weer jammer vind want je hebt alle user informatie al behalve het nieuwe id voor dit object. En andersom zul je eerst een user object moeten aanmaken zonder een id, en deze na insertion toevoegen. Kip en Ei -achtig.

Ik neig vaak wel naar de manier van whoami. Een user object (entiteit) is 'dom' en is in principe alleen een data container. Een manager kan via getters en setters wijzigen doervoeren.

[ Voor 37% gewijzigd door Verwijderd op 16-06-2009 11:12 . Reden: Ook even mijn visie op het probleem gepost ]


Acties:
  • 0 Henk 'm!

  • martijngr85
  • Registratie: Maart 2009
  • Laatst online: 05-08 10:32
Ik geloof dat ik wat los gemaakt heb met mijn Interface vraag :) Interessant om te lezen allemaal, maar ik moet zeggen dat ik de implementatie nog niet helemaal begrijp, echter de theorie begint te dagen.. Zou iemand een code voorbeeld kunnen geven van het ophalen van alle gebruikers op een interface manier? De code van Nick_S bevat ik niet volledig. Op het moment programmeer ik op zijn eerste code voorbeeld manier...

Acties:
  • 0 Henk 'm!

  • jip_86
  • Registratie: Juli 2004
  • Laatst online: 00:52
Nick_S schreef op dinsdag 16 juni 2009 @ 10:54:
[...]

Ik niet. Ik begin steeds meer een hekel aan NULL te krijgen. ;) Alle if constructies om null checks te doen zijn in eigen code bijna altijd overbodig.

Als je een user opvraagt aan de hand van zijn ID verwacht je dat hij er is. (Je verzint, neem ik aan, geen ID's) Is deze er dus niet, is dat in mijn ogen een exceptie.

Als je de users d.m.v. hun achternaam wil ophalen is dat een set (geen dubbele) van users. Deze collectie kan ook nooit NULL zijn, het kan wel een lege collectie zijn. Aangezien het geen zin heeft om hier elementen uit weg te gooien, aangezien je daar een deleteUser voor hebt, is het ook nog een immutable collection.
Dan moet je toch alsnog gaan checken op Exceptions ?

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
martijngr85 schreef op dinsdag 16 juni 2009 @ 11:09:
Ik geloof dat ik wat los gemaakt heb met mijn Interface vraag :) Interessant om te lezen allemaal, maar ik moet zeggen dat ik de implementatie nog niet helemaal begrijp, echter de theorie begint te dagen.. Zou iemand een code voorbeeld kunnen geven van het ophalen van alle gebruikers op een interface manier? De code van Nick_S bevat ik niet volledig. Op het moment programmeer ik op zijn eerste code voorbeeld manier...
Het tweede code-voorbeeld van Nick_S is nochtans simpel:
Ipv dat die service zelf een bepaalde repository creeërt, krijgt die service een repository als argument mee in z'n constructor.
Dat wil dus zeggen dat die service niet 'vasthangt' aan een bepaalde implementatie van die repository. (De implementatie die moet gebruikt worden, is nl. niet hard gecodeerd in de service). (== dependency injection)

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • martijngr85
  • Registratie: Maart 2009
  • Laatst online: 05-08 10:32
En wat zou er dan kunnen staan in de interface UserService? Een interface kan toch geen implementaties van methods bevatten?

Acties:
  • 0 Henk 'm!

  • Jaap-Jan
  • Registratie: Februari 2001
  • Laatst online: 11-09 13:16
Java:
1
2
3
interface UserService {
    public void DoeIetsMetUsers();
}


Meer is het niet. Maar je hebt Head First Design Patterns gehad, dan zou je deze regel moeten kennen:
Program to an interface, not an implementation
En dat is precies wat je dat als je 'praat' tegen UserService. Dat is een interface, die geïmplementeerd wordt door UserServiceImplementation, maar hoe die zijn dingen voor elkaar bokst, boeit niet zo. :)

| Last.fm | "Mr Bent liked counting. You could trust numbers, except perhaps for pi, but he was working on that in his spare time and it was bound to give in sooner or later." -Terry Pratchett


Acties:
  • 0 Henk 'm!

Verwijderd

Java:
1
2
3
4
5
6
public interface DataProvider {
    public User getUser(int id);
    public boolean userExists(String firstname, String lastname);
    public List<User> getAllUsers();
    public List<User> getUsersFrom(String city);
}
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MySQLProvider implements DataProvider {
    private Connection conn;
    
    public MySQLProvider(String connectionstring) {
        //setup db conn
    }

    public User getUser(int id) {
        //implementatie
    }
    
    public boolean userExists(String firstname, String lastname) {
        //implementatie
    }
    
    ...
}
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class OracleProvider implements DataProvider {
    private Connection conn;
    
    public OracleProvider(String connectionstring) {
        //setup db
    }
    
    ...

    public List<User> getAllUsers() {
        //implementatie
    }
    
    public List<User> getUsersFrom(String city) {
        //implementatie
    }
}
Java:
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
public class UserManager{
    private DataProvider provider;
    
    public UserManager (DataProvider provider) {
        this.provider = provider;
    }
    
    public DataProvider getProvider() {
        return provider;
    }
    
    
    public static void main (String[] args) {
        String conn = args[0];
        boolean mysql = args[1].equals("mysql");
        
        DataProvider provider;
        if (mysql) provider = new MySQLProvider(conn);
        else provider = new OracleProvider(conn);
        
        UserManager um = new UserManager(provider);
        um.getProvider().userExists("jan","smit");
        um.getProvider().getUsersFrom("amsterdam");
    }
}


Niet getest maar het idee zal duidelijk zijn hoop ik =)
Eventueel maak je een facade om direct de provider methoden via de usermanager op te halen.

[ Voor 3% gewijzigd door Verwijderd op 16-06-2009 11:37 ]


Acties:
  • 0 Henk 'm!

  • martijngr85
  • Registratie: Maart 2009
  • Laatst online: 05-08 10:32
Klopt, ik ben bekend met die regel, alleen nooit echt door laten dringen wat ze daar nu precies mee bedoelen. Ik denk dat dat nu een beetje duidelijk wordt...

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
martijngr85 schreef op dinsdag 16 juni 2009 @ 11:18:
En wat zou er dan kunnen staan in de interface UserService? Een interface kan toch geen implementaties van methods bevatten?
Een interface niet nee, maar je hebt natuurlijk ook classes die die interface implementeren.

Als jij in een class dit doet:

code:
1
2
3
4
5
6
7
8
9
public class SomeClass
{
   ISomeInterface _melp;

   public SomeClass( ISomeInterface x )
   {
        _melp = x;
   }
}


Dan gebruik je die dus zo:

code:
1
SomeClass c = new SomeClass(new SomeInterfaceImplementationX());

waarbij 'SomeInterfaceImplementationX natuurlijk de ISomeInterface implementeert.
Echter, jij kan daar evengoed een ander object als argument gaan meegeveln, zolang dat object die ISomeInterface maar implementeert.
SomeClass zal dan de implementatie gaan gebruiken die jij hebt meegegeven, zonder dat 'SomeClass' precies hoeft te weten welke implementatie het is. Die weet enkel dat het een ISomeInterface is.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • martijngr85
  • Registratie: Maart 2009
  • Laatst online: 05-08 10:32
Het concept begint me duidelijk te worden, bedankt :) Alleen vraag ik me nu wel af of dit nut heeft bij een User? Bij de data providers kan ik het me goed voorstellen, alleen bij een User iets minder. Of is het gewoon een goede eigenschap om jezelf deze wijze van programmeren aan te leren?

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
martijngr85 schreef op dinsdag 16 juni 2009 @ 11:47:
Het concept begint me duidelijk te worden, bedankt :) Alleen vraag ik me nu wel af of dit nut heeft bij een User? Bij de data providers kan ik het me goed voorstellen, alleen bij een User iets minder. Of is het gewoon een goede eigenschap om jezelf deze wijze van programmeren aan te leren?
Der wordt ook nergens gezegd dat je een IUser interface moet hebben. :)
(En voor entities zou ik het dus ook niet doen : ) )

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • martijngr85
  • Registratie: Maart 2009
  • Laatst online: 05-08 10:32
Haha dat is waar. We kwamen er op omdat jij (whoami) begon over een IUserRepository. Van daaruit begon het interface verhaal. Heb zojuist nog even gelezen waaorm je dat doet, maar geloof niet dat dat voor mij van toepassing is (moet ook eerlijk zeggen dat ik het niet 100% begrijp).

Acties:
  • 0 Henk 'm!

  • martijngr85
  • Registratie: Maart 2009
  • Laatst online: 05-08 10:32
Jaap-Jan schreef op dinsdag 16 juni 2009 @ 11:22:
Java:
1
2
3
interface UserService {
    public void DoeIetsMetUsers();
}


Meer is het niet. Maar je hebt Head First Design Patterns gehad, dan zou je deze regel moeten kennen:


[...]


En dat is precies wat je dat als je 'praat' tegen UserService. Dat is een interface, die geïmplementeerd wordt door UserServiceImplementation, maar hoe die zijn dingen voor elkaar bokst, boeit niet zo. :)
Dus met die regel bedoelen ze "programmeer interfaces, de implementaties is voor de rest niet interessant (architectisch gezien dan)"

Acties:
  • 0 Henk 'm!

Verwijderd

De IUserRepositor is verglijkbaar met de DataProvider in mijn voorbeeld. Alleen met een ander naampje voor het beestje.

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
martijngr85 schreef op dinsdag 16 juni 2009 @ 11:59:
Haha dat is waar. We kwamen er op omdat jij (whoami) begon over een IUserRepository. Van daaruit begon het interface verhaal. Heb zojuist nog even gelezen waaorm je dat doet, maar geloof niet dat dat voor mij van toepassing is (moet ook eerlijk zeggen dat ik het niet 100% begrijp).
Hij bedoelt een I-UserRepository, niet een IUser-Repository ;)

https://niels.nu


Acties:
  • 0 Henk 'm!

  • martijngr85
  • Registratie: Maart 2009
  • Laatst online: 05-08 10:32
Bedoelen jullie beiden nu hetzelfde? (Khainer en Hydra)

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
martijngr85 schreef op dinsdag 16 juni 2009 @ 14:39:
Bedoelen jullie beiden nu hetzelfde? (Khainer en Hydra)
Ja :)

https://niels.nu

Pagina: 1