Toon posts:

Referentie vanuit UI naar Servicelaag en naar Repositories?

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Intro
Stel ik heb 't volgende systeem opgezet:

Ik heb repositories die alle CRUD-acties verzorgen voor een bepaalde class. Zo heb ik bijvoorbeeld MedewerkerRepository.
De MedewerkerRepository bevat methods als GetAll(), GetByID(), SaveOrUpdate() etc.

Verder heb ik een Domein laag, waarin alle domein objecten zitten, zoals Medewerker. Een Medewerker class bevat zowel data (Naam, Salaris, Functie etc.) als functionaliteit (VerhoogSalaris())

Ik heb ook een servicelaag, waarin functies zitten als OntslagMedewerker, die vervolgens zorgt dat de DatumUitDienst van een Medewerker op today wordt gezet, zijn salaris op 0 wordt gezet, en zorgt dat via de E-mailService de administratie een verzoek krijgt om een ontslagbrief te maken.

Tot nu toe geen vragen, maar....

Vraag
Stel ik wil nu een lijstje op het scherm tonen met alle medewerkers die Jansen heten. De Repository bevat in ieder geval de functie om dit lijstje op te hoesten. Alleen ik had in eerste instantie het idee dat de User Interface alleen tegen de Domain Objecten en de Service Laag aan praat, en dat de Service Laag de interactie met de Repositories doet.
Maar als ik dat zo doe, dan moet ik dus in mijn Service Laag ook een functie GetAll() maken, die eigenlijk alleen maar de Repository aanroept, en verder niet zoveel doet. Niet zo'n probleem natuurlijk, maar een beetje zonde van het werk.
Zouden jullie ervoor kiezen om de User Interface ook de Repositories aan te laten spreken, of toch alles via de Service Laag te doen?

Acties:
  • 0 Henk 'm!

  • djluc
  • Registratie: Oktober 2002
  • Laatst online: 25-09 19:17
In je service laag bepaal je welke gegevens beschikbaar in je view zijn. Dus iets als:

$view->employeeList=$employeeModel->getAll();

vind ik een goede oplossing.

Acties:
  • 0 Henk 'm!

Verwijderd

Gewoon de Service Laag dit af laten handelen. Stel dat je het lijstje wilt filteren, pagination toepassen, enz. Dan wil je dat allemaal afhandelen in die Service Laag.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 17:09
Verwijderd schreef op woensdag 03 december 2008 @ 11:06:
Intro
Stel ik heb 't volgende systeem opgezet:

Ik heb repositories die alle CRUD-acties verzorgen voor een bepaalde class. Zo heb ik bijvoorbeeld MedewerkerRepository.
De MedewerkerRepository bevat methods als GetAll(), GetByID(), SaveOrUpdate() etc.
Even een side - note; je hebt niet voor iedere class een repository.
Enkel een repository per aggregate-root.
Vraag
Stel ik wil nu een lijstje op het scherm tonen met alle medewerkers die Jansen heten. De Repository bevat in ieder geval de functie om dit lijstje op te hoesten. Alleen ik had in eerste instantie het idee dat de User Interface alleen tegen de Domain Objecten en de Service Laag aan praat, en dat de Service Laag de interactie met de Repositories doet.
Tja ... Is de Repository dan geen deel van je Domain ? Volgens mij zijn repositories first class citizens binnen het domein.
Zowiezo vind ik dat je je repository vanuit je UI kunt aanroepen indien dat nodig is.
Hoe ga je nl. je DB - sessies afhandelen ? Ik bedoel maar: wie (welk onderdeel) gaat er sessies starten / transactie-beheer doen ?

Als je met een Service laag werkt, waarbinnen je dit allemaal afhandelt (je service laag heeft weet van de context), dan kan je er voor kiezen om dit gewoon consistent te houden, en er dus ook de nodige voorzieningen treffen binnen je service laag .... Mja, ik denk niet dat er een eenduidig antwoord is.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Wij maken meestal gebruik van XXXRequestEntity classes waarmee wij 'zoekopdrachten' kunnen uitvoeren. In jouw geval zou dat dan een EmployeeRequestEntity zijn met bijvoorbeeld properties zoals naam, geboortedatum, functie, etc. De GetBySearch methode accepteert een instantie van deze class en bouwt de query op basis van de velden welke geen 'default' of null waarde bevatten.

Vanuit je interface zet je dan de properties van de EmployeeRequestEntity en die geeft je vervolgens door aan de service laag.

Service lagen werken daarnaast in zo'n 80% via het facade principe en zullen in veel gevallen het verzoek doorzetten naar de repository. De service laag kan eventueel ook besluiten caching toe te passen. Theoretisch kun je later dan ook eenvoudiger wisselen van database naar webservice.

Overigens hebben wij geen GetAll() methodes omdat wij geen situaties hebben waarin wij altijd *alle* records terug willen hebben. Wij hebben of een bepaald record nodig of een bepaalde subset.

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

Verwijderd

Zoals ik nu tegen DDD aankijk is je service laag een heel dunne laag die een aantal basale kerntaken heeft en in feite de API vormt van je applicatie. Het is een toegangslaag die je domein en storage scheidt van je presentatie. Of je data nou wilt weergeven op een website in HTML, in een java desktop applicatie of data wilt doorsturen n.a.v. een SOAP request, je wilt deze data het liefst ophalen via je service laag.

De service laag is primair verantwoordelijk zaken als het beheren van transacties boundaries en toegangscontrole. Security zou je in mijn ogen heel mooi op je service laag kunnen implementeren. Wanneer je vanuit de UI direct een Repository gaat aanroepen, dan is dat vragen om herhalio's. Je zal immers ook nog ergens de toegang moeten controleren.

In jou geval zou ik dus inderdaad een getAll methode schrijven op de Service en een getAll methode schrijven op de Repository. Het grote verschil is dat de Repository en je Domein Objecten geen weet hebben van de transaction boundaries. Dat is nou exact wat je service laag weet.

In mijn ogen definieer je in de service laag wat je applicatie allemaal kan in de vorm van grote brokken. Deze grote brokken zijn onderverdeeld in kleinere acties op je domein objecten en Repositories.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MoneyTransferService {
  public function transfer(Account $from, Account $to, $amount) {
    $this->database->startTransaction();

    try {

      $from->debit($amount); // throws NotEnoughMoneyException
      $to->credit($amount);

      $this->database->commit();

    } catch (NotEnoughMoneyException $e) {
      $this->database->rollback();
      throw new TransferException($e);
    }
  }
}


Zoals je in mijn voorbeeld kan zien regelt de service laag het starten van de transactie en probeert hij kleinere acties uit te voeren op de domein objecten. Je service laag is dus zo kaal mogelijk. Er zit geen BL in.

In jouw geval betekent het echter dat de methode die je wilt aanroepen binnen de service laag, gelijk is aan de repository en dat het een droge delegate is waar wat transactie code omheen staat en toegangscontrole.

Voor mijzelf geldt de regel: een lagere laag heeft geen weet van een hogere laag. Een elke laag wil zo min mogelijk lagen de diepte in springen. Zo zou ik nooit vanuit de view direct een Repository aanspreken omdat ik dan bang ben dat ik mezelf in de toekomst ga herhalen. De transactie code en toegangscontrole code wil ik namelijk op een plaats hebben staan: in de service.

[edit]
Transactie beheer zou ik nooit in de Repository doen omdat je dan stateful Repositories krijgt. Dat is geheid vragen om problemen. De methoden in een Repository zijn zo atomair dat je daar niets anders wilt doen dan iets wegschrijven of een object ophalen.

[ Voor 5% gewijzigd door Verwijderd op 05-12-2008 17:55 ]

Pagina: 1