I mitt land vil du ikke gjøre det gjennom skolen uten å lese hvordan Goethes Faust klager, Jeg har studert nå filosofi - og rettsvitenskap, medisin, - og selv, alas! Teologi - Gjennom og gjennom med glede! - Her står jeg nå, dårlig dumme.
Dessverre har ingen av hans innsats og studier hjulpet legen til å oppleve det som holder verden sammen i sine innerste folder.
Og her er vi i IT: Vi har studert språk og rammer, biblioteker og likevel - IE! Alt gjennom og gjennom med ardor ivrig. Men hvor mange ganger har vi fokusert på hva som holder søknaden sammen i sine innerste folder? Dagens emne er forretningsdomenet.
Forretningslogikk er noen ganger ansett for å være unik, og det er per definisjon! Hvis forretningslogikken til et program ikke ville være unikt, ville det ikke være nødvendig å skrive et søknad, da det allerede finnes en eksisterende løsning (med unntak av når et program eksisterer, men ikke er tilgjengelig). Derfor ser mange utviklere seg selv som pionerer, for å dristig gå der ingen har gått før. Romantikere til side, mens forretningslogikken selv kan være unik i en bemerkelsesverdig grad, er teknikkene for å implementere det ikke. Derfor ble smarte prosessmodeller som Rational Unified Process eller Scrum sammen med teknikker som iterative og inkrementelle utviklingssykluser invitert. Talenterte programvarearkitekter har utarbeidet tilnærminger til programvareutforming også; blant dem Eric Evans hvem mente begrepet Domene Driven Design i sin bok med samme tittel.
Utviklere går dristig, hvor ingen har gått før.
Jeg gir en oversikt over hvordan Domain Driven Design kan påvirke konsulentprosessen, samt de grunnleggende konseptene for å designe en domenemodell. Til slutt vil vi diskutere infrastrukturkravene som trengs for å implementere et domene med letthet.
La oss si at du er en programvarearkitekt på et ikke-trivielt program med et ikke-trivielt domene, som kjernemotoren til et stort logistikkfirma. Mange mennesker går med i planleggingsforhandlingene, blant annet prosjektledere, kontoansvarlige, markedsføring, konsulenter og så videre. Ikke alle er nødvendig for å få jobben (jeg vil ikke dele mine meninger om hvem dette gjelder), men to personer vil spille en avgjørende rolle i prosessen med kravsteknikk: du, arkitekten og domeneseksperten.
EN programvarearkitekt (i hvert fall i næringslivskontekst) bør ha en veldig god abstrakt forståelse av hvordan prosesser fungerer, hvordan de utformes og optimaliseres.
Det er sant fordi forretningsapplikasjoner hovedsakelig handler om å designe effektive og vakre digitale ekvivalenter av forretningsprosesser. EN domene ekspert bør ha en grundig kunnskap om et bestemt sett med prosesser, nemlig prosessene som finner sted i logistikkfirmaet, og som bør gjenspeiles av søknaden. Jeg fant ut at forretningskonsulenter, salgssjef og markedsføringseksperter gjør noen gode og verdifulle poeng underveis, men så lenge du ikke har noen i teamet som fikk hendene skitne i mange års erfaring, vil prosjektet mislykkes. Eksempelvis bør domeneteksperten kjenne bredden på lasterampen på depotet, og hvis det er nok plass til å installere en strekkodeskanner.
Så det er deg, spesialisert på digitale forretningsprosesser, programvareutvikling og [fyll inn favorittverktøyene dine her], og en ekspert på logistikk med kunnskap om selskapets kunder, ansatte og den daglige rutinen. Sjansen er, du snakker i kryssformål. Domain Driven Design foreslår noen strategier som kan danne en kraftig teknisk konsulenttjeneste. Her er min:
Høres ut som moro! La oss dykke inn i detaljene.
I alle bransjer har hver ekspertgruppe sin egen terminologi. Det er raffinert i alle selskaper og beriket med selskapets spesielle vilkår og produktnavn. Tenk på IT: Når folk som oss møtes for seriøs nektespak, hvem ville ellers forstå et ord? Det samme gjelder for domenet ditt, og det første du må gjøre er å definere et sett med vilkår. Gå gjennom hele settet av prosesser som programvaren skal gjenspeile og lytte nøye til hvordan domenet ekspert beskriver det. Eventuelle domenespesifikke termer bør defineres på en måte som ordbøker gjør. Du bør være oppmerksom på ord som høres kjent, men ikke er i den konkrete sammenhengen. Noen selskaper har aldri gjort jobben før, selv om det er verdifullt for andre områder.
Lag en dedikert ordliste over allestedsnærværende vilkår, vær sikker på at den blir godkjent av klienten, og ta betalt for konsulentprosessen! En ordliste kan se slik ut:
Et utdrag fra en ordliste.Legg merke til hvordan en veldefinert ordliste allerede angir avhengigheter og foreninger. Som rekkefølge, som er vert for flere elementer. Du vil sikkert ha klasser for dem i din forretningslogikk! Din Rekkefølge
klassen vil antagelig ha en metode som getItems ()
. Uten å ta hensyn til programmeringsteknikker, kan en ordliste legge grunnlaget for domenemodellen din! Sammen med det bygger du et språk som brukes over hele prosjektet: i post, i møter, og definitivt i kode! Koden din bør gjenspeile domenet; Derfor må det defineres i ordlisten. Her er en tommelfingerregel: Når du oppretter en klasse som ikke er oppkalt etter en oppføring i ordlisten, kan det ikke bli definert ditt allestedsnærværende språk nok.!
Under mørket har vi flyttet utsikten over kravene! Normalt beskriver en klient hva den skal-skrivte-programvaren skal gjøre. En typisk beskrivelse kan være: "Vi trenger en måte å legge til notater på en klient og skrive ut dem." Dette er et godt utgangspunkt, men det fokuserer ikke på bedriftsdomenet. Det introduserer en slags brukergrensesnitt, utskriftsfunksjonalitet og enda mer. Du har sikkert behov for det i søknaden din, men det er ikke en del av domenet. Domene Driven Design fokuserer på modellering av den sanne hensikten med et program: bedriftsdomenet.
Alt annet skal oppstå derfra, når domenet er ferdig. Bryteren er følgende: Ikke implement prosesser, og bygg et rent domen som reflekterer kundens behov i objekter. En måte å visualisere den øvre klientbeskrivelsen på vil være slik (getters og setters blir bare lagt til når det trengs for forståelsen):
Et enkelt diagram som gjenspeiler det nødvendige domenet.Nå har vi et sett av klasser og foreninger som bare gjør gjenspeiler definisjonene fra vår ordliste. Er denne modellen i stand til å utføre de nødvendige oppgaver? Sikker! Du trenger en PrinterService
og et brukergrensesnitt et sted i appen din, men de trenger bare å hente data fra domenet. De er ikke nødvendige akkurat nå, og implementeringen vil ikke være avgjørende for utfallet.
Filosofien til DDD er basert på forutsetningen om at et nøye designet domenelag kan utføre alle nødvendige prosesser med letthet. En domenemodell er skalerbar, da den ikke er bygget for å tilfredsstille en gitt oppgave, er den bygget for å reflektere et forretningskonsept. Det er utskiftbart, da det ikke er bundet til noen bestemt programvare, ikke engang til et brukergrensesnitt. Du kan bruke samme modell i strekkodeskanneren på lasteplanen på depotet! Som vi ser i neste kapittel, er det ikke engang bundet til andre komponenter som bygger applikasjonen din.
I en av mine nyere artikler skrev jeg om å anvende KISS-prinsippet.
I en av mine nyere artikler skrev jeg om å anvende KISS-prinsippet: De fleste systemer fungerer best hvis de holdes enkle, i stedet for komplekse. Vel, når det gjelder å implementere et domene basert på DDDs filosofi, kan du møte en ganske radikal tilnærming i den moderne verden av rammer, mønstre og disipliner. for eksempel, implementere et vanlig objekt i bare det enkle språket du ønsker. Ingen rammeavhengigheter, ingen bibliotekskonvensjoner, ingen spor av noen API, ingen fancy navn. Bare et vanlig gammelt objekt (siden et konsept ikke blir tatt alvorlig uten et fancy navn i Java-verdenen, fikk de en der borte).
Når vi ønsker å reflektere domenemodellen, er et avgjørende punkt å definere sin tilstand. I objektorientert programmering defineres tilstanden til en objekt av tilstanden til dens egenskaper. På samme måte defineres tilstanden til domenemodellen av tilstanden til dens objekter. Derfor må vi ha en måte å tydelig definere tilstanden til objekter. Hvis vi ikke kunne gjøre det, ville vi mislykkes i enkle brukstilfeller som "Hvor mange ordrer er det?" Fordi svaret alltid krever kunnskap om tilstanden til alle Rekkefølge
objekter i et domene og en måte å identifisere og skille dem fra. DDD definerer to typer objekter: Enheter og verdiobjekter.
en enhet er et kjent konsept, hvis du er kjent med relasjonsdatabaser.
Tabeller i en relasjonsdatabase har vanligvis en unik identifikator som skiller en rad fra en annen. Det samme gjelder for enheter. En enhet må ha en klar identifikator som er unik i hele systemet. For en bestilling kan dette være en eiendom av typen uint, navngitt ordrenummer
. Selvfølgelig vil du se på ordlisten din, der riktig uttrykk skal defineres.
En enhet forblir den samme når enkelte egenskaper endres. For eksempel kan du legge til eller fjerne elementer fra en ordre, men det ville være den samme bestillingen. Hva skjer når du endrer ordrenummer
? Vel, fra POV av domenet ditt, slettes en ordre mens en annen er opprettet.
EN verdiobjekt er enkel beholder for informasjon. Det er uforanderlig når det er opprettet. Endring av en eiendom betyr at du vil endre verdiobjektet. Et verdiobjekt defineres av alle dets egenskaper; det trenger ikke en unik identifikator. Hele objektet er en. Et eksempel på et verdiobjekt ville være en OrderAddress
, som den er definert av mottakerens navn, adresse og by. Hvis du vil endre en eiendom, for eksempel byen, vil OrderAddress endres helt.
Å dele objekter i verdiobjekter og enheter er viktig for å definere tilstanden til domenet ditt - da dette er grunnarbeidet for å identifisere komponenter. Men det er like viktig å definere dem for å ha et skalerbart, vedlikeholdbart domene. Enheter er representasjon av virkelige verdensobjekter som Personer, Ordrer eller Elementer. Verdiobjekter er beholdere for informasjon som farger eller adresser, og de er gjenbrukbare og delbare mellom enheter eller til og med hele systemet. Definere dem kan ta litt øvelse, da det er avhengig av brukssaken om du har et verdiobjekt eller en enhet.
Når vi ser tilbake på abstraktet av vår ordliste, kan vi se forbindelser og avhengigheter mellom objektene våre i domenelaget. I DDD kalles dette foreninger og det er modellen for samspill som foregår.
For eksempel er elementer en del av bestillingen. Hvis vi ville behandle seg mot en relasjonsdatabase, ville dette være et til mange forhold (eller 1: n). Hvis hver ordre ville ha akkurat en OrderAddress, ville det være et ett-til-ett-forhold. Siden vi ikke bryr oss om relasjonsdatabaser og bare bryr oss om å fullføre domenet, kan forholdet enkelt uttrykkes med to metoder i klassen Ordre: getItems ()
og getOrderAddress ()
. Merk at den første er flertallet (som det er mange elementer) og det andre er entall. Hvis du vil ha et mange til mange forhold, vil du gi begge klassene en getter-metode. Selvfølgelig trenger du også settere-jeg har utelatt dem for å holde eksemplene lette.
I DDD prøver vi å unngå mange til mange relasjoner, da de pleier å legge kompleksitet til domenet. Teknisk betyr det at to objekter må holdes synkronisert i løpet av deres livssyklus, og å holde ting i synkronisering kan føre til brudd på DRY-prinsippet. Derfor bør modellfinansieringsprosessen strebe etter enkelhet. I mange tilfeller er en forening sterkere i en retning enn den andre, og det er en god ide å omstrukturere strukturen til et forhold til en til mange. Sjekk om foreningen er relevant for forretningslogikken i søknaden din. Hvis det bare skjer i ikke-kjerne og sjeldne brukstilfeller, vil du kanskje se etter en annen måte å motta den nødvendige informasjonen på.
Foreninger bygge et tre av objekter, og du skal ende opp med en foreningskonstruksjon hvor hvert objekt kan hentes gjennom getter-metoder. Dette er en foreldre-barn konstruksjon som til slutt fører til ett rot objekt. Dette kalles aggregering i DDD. En god design resulterer til slutt til ett aggregat som er i stand til å reflektere hele domenet. For øyeblikket har vi bare sett på en liten del av vår ordliste, men det ser ut til at en klient er vårt rotaggregat:
Klientobjektet er forelder for alle domenenavn.Aggregater er en viktig del, da DDD prøver å isolere domenet fra det omkringliggende programmet. Hvis vi liker å ha informasjon om en klient, ber vi om et rotaggregat og kan krysse gjennom sine barn for å få tilgang til informasjon gjennom et klart grensesnitt av getters og setters.
DDD er som salg, det gir et ansikt til kunden, aggregatet til det omkringliggende systemet. Derfor gir den tilgang til et strukturert sett av prosesser relevant informasjon og metoder; for eksempel bestillingen.
Domene Driven Design er som salg, det gir et ansikt til kunden.
Det omkringliggende programmet får tilgang til et aggregat gjennom repositorier, som egentlig er en slags fasade. Med andre ord: Et domeneobjekt er et aggregat hvis det har et lager. Oppbevaringssteder gir metoder for å søke etter aggregater. Eksempler kan være findClientByEmail (streng e-post)
eller bare findAll ()
. De utfører også oppdateringer og legger til nye objekter på domenet. Dermed har de sannsynligvis metoder som legg til (klient newClient)
eller slett (Client toBeDeletedClient)
.
Med et aggregat får du bare tilgang til barn gjennom foreldrene. For eksempel gir en klientaggregat tilgang til alle bestillinger av klienten. Men hvis du trenger tilgang til dataene fra et annet perspektiv enn klienten, kan du etablere et andre aggregat. La oss si at du vil ha en liste over alle bestillinger, uansett hvilken kunde de ble plassert. Et ordrearkiv vil få jobben gjort!
Domenerlaget og dets repositorier.Siden depotet er inngangspunktet for det omkringliggende programmet til domenelaget, er det der andre spillere går inn i området. Husk at vi har å gjøre med enkle gjenstander for nå.
Har du spurt deg selv hvordan dette blir ekte? Dette er hvor infrastruktur kommer inn. DDD er en utmerket følgesvenn for rammer, da den er bygget på enkle objekter, med en enkel ordning av verdiobjekter, enheter og aggregater. Men siden enkelheten er kraft i IT, er vi nå i stand til å outsource hele infrastrukturdelen. La oss ta en titt under hetten, og hvordan DDD kan spres rundt en applikasjon.
Du har kanskje lagt merke til at vårt fokus på domenet utelukket et utholdenhetslag, så vel som vanlige ting som visninger eller kontrollører fra vår gjøremålsliste. Hele applikasjonen kan bestå av mye mer komplekse ting enn bare enkle objekter, og jeg vil påpeke noen få skritt som må gjøres for å ledet domenet og appen sammen, samt hvilke implementeringsstrategier som eksisterer. Jeg vil lage noen eksempler basert på FLOW3, et søknadsramme med hovedfokus for å tilby DDD-infrastruktur. Det er ikke nødvendig, men det vil ikke skade hvis du leser min introduksjon. For å bruke bedriftsdomene til et program, er følgende trinn vanlige:
Når du ser på kommentarene på artikkelen til Aspect Oriented Programmering (AOP), vil du se en interessant diskusjon om hvorvidt et rammeverk skal legge til sitt fotavtrykk via kommentaranbefalinger. Tilnærmingen i FLOW3 er basert på hvordan Domain Driven Design er implementert. Ta en titt på denne koden:
/ ** * En klient * * @ FLOW3 \ Scope ("prototype") * @ FLOW3 \ Entity * / klasseklient / ** * Klientens navn. * * @ FLOW3 \ Validate (type = "Text") * @ FLOW3 \ Validate (type = "StringLength", alternativer = "minimum" = 1, "maksimum" = 80) * @ORM \ Kolonne ) * @var streng * / beskyttet $ navn; / ** * Hent kundens navn * * @return string Klientens navn * / offentlig funksjon getName () return $ this-> Name; / ** * Angir denne kundens navn * * @param string $ Navn Klientens navn * @return void * / public function setName ($ navn) $ this-> name = $ name;
Dette er en veldig enkel klasse, og det inneholder ikke mye forretningslogikk, men dette vil trolig endre seg når søknaden vokser. FLOW3 er tilstede gjennom noen kodeanbefalinger. Det definerer klassen som en enhet og legger til noen valideringsregler som skal brukes (dette er valgfritt). Legg merke til at det er en merknad som heter @ORM \-kolonne (lengde = 80)
. Dette er en informasjon for persistenslaget, og vi kommer tilbake til dette på et øyeblikk.
FLOW3 bruker merknader her for å holde domenet rent. Du er fri til å bruke klassen noe annet sted, siden det fremdeles er en vanlig gjenstand. Du kan velge å bytte til symfony rammeverk, som bruker det samme utholdenhetslaget (doktrinen), derfor vil koden nesten fungere ut av boksen. Ved å skyve rammekonfigurasjonen utenfor PHP-tolkens omfang forblir domenet et vanlig gammelt PHP-objekt. Du kan gjenbruke det selv uten noe rammeverk i det hele tatt.
Men nå som rammen er klar over objektet, kan den nå beregne kravene til en MySQL database tabell. For å lagre forekomster av klasseklienten, ville FLOW3 (og Doctrine as Persistence Framework) utføre følgende trinn for deg:
Egenskapsdefinisjonen for elementene i vår bestilling kan se slik ut:
/** * Gjenstandene. * * @ORM \ OneToMany (mappedBy = "rekkefølge") * @ORM \ OrderBy ("price" = "ASC") * @var \ Doctrine \ Common \ Collections \ Collection<\LogisticApp\Domain\Model\Item> * / beskyttet $ elementer;
Legg merke til at dette returnerer en doktrinsamling, som er en slags innpakning for en matrise, som ArrayLists i Java. I hovedsak betyr dette at alle elementene må være av den oppgitte typen, i dette tilfelle element. Jeg har valgt å legge til en ordreerklæring om hvordan jeg vil at samlingen skal organiseres (etter varens pris).
Motparten i produktklassen kan være:
/** * Rekkefølgen. * * @ORM \ ManyToOne (inversedBy = "items") * @var \ LogisticApp \ Domain \ Model \ Order * / beskyttet $ rekkefølge;
Det er bare toppen av et isfjell, men det bør gi deg en ide om hvordan ting kan automatiseres: Lære gir en kraftig strategi for å kartlegge foreninger til tabellene der den lagrer objektet. For eksempel, siden artiklene ville oversette til en til mange forhold (en ordre kan ha mange elementer) i databasen, ville doktrinen stille en utenlandsk nøkkel for ordren til elementbordet. Hvis du bestemmer deg for å legge til et lager for elementet (gjør det til et aggregat), kan du få tilgang til a findByOrder (bestillingsordre)
metode. Det er grunnen til at vi ikke bryr oss om databaser eller utholdenhet under domeneskaping - det er noe som et rammeverk kan ta vare på.
Hvis du er ny på persistensrammer, kalles veien for å kartlegge objekter til en relasjonsdatabase ORM (Object-Relational-Mapping). Det har noen ytelses ulemper, som hovedsakelig skyldes de ulike tilnærmingene som relasjonsdatabaser og objektmodellen har. Det er lange diskusjoner om det. Men i moderne CRUD-apper (ikke bare domene drevet), er ORM veien å gå-hovedsakelig for vedlikehold og utvidbarhet grunner. Du bør imidlertid vite din ORM og ha en god forståelse av hvordan det fungerer. Tror ikke at du trenger lenger kunnskap om databaser lenger!
Som du kanskje har lagt merke til, kan objektene dine være stille komplekse og ha en lang traversal linje hvis de har mange barn, som i sin tur har mange egne barn.
Derfor, når depotet henter data fra en database, må de omdannes til objekter på en intelligent måte. Siden vi nå har et vedvarende lag involvert, er transformasjonen mye mer kompleks enn bare å instantiere et objekt. Vi må klare traversal linjen ved å redusere de relevante samtalene til databasen til et minimum. Ikke alle barn er alltid nødvendig, så de kan hentes på forespørsel.
Noen objekter vil være verdien objekter som må opprettes bare én gang, noe som kan spare mye minne. Derfor trenger et domenelag en smart fabrikk som genererer objektene for deg. Derfor, i moderne rammer, den ny
operatør anses å være altfor lavt nivå for moderne applikasjoner. FLOW3 går langt for å gi mulighet til å instantiere objekter med ny
søkeord, men bakgrunnskompilasjonen endrer automatisk ren objektiv til kraftig objektstyring. Noen funksjoner som objektleder / fabrikk skal kunne, uansett hvilken ramme du bruker, er:
Du kan ha rynket på den siste setningen. Gjennom hele artikkelen har jeg lagt vekt på å bruke vanlige objekter i domenet, og jeg overtrådte selv paradigmetet "Gjenta ikke selv" og nevnte det flere ganger fordi det er så viktig å DDD. Og nå forteller jeg deg at du har avhengigheter og tjenester som må være en del av domenet ditt ...
Det er en trist sannhet i den virkelige verden: Det er ikke slikt som et rent domene. Du kommer nesten aldri til å møte en klient som starter fra bunnen av; så må du tilfredsstille forhold som eldre systemer. De kan ha en fryktelig gjennomføring, men selskapet kan ikke kvitte seg med det. Du må kanskje ringe tjenester og APIer og hente data fra ulike tredjeparter, og disse eldre systemene påvirker bedriftsdomenet.
Alt vi har diskutert hittil er viktig, men spørsmålet om hvordan et rammeverk løser avhengigheten av ikke-domene tjenester er kritisk for en ren Domain Driven Design. Det er derfor FLOW3-teamet brukte en enorm innsats på implementering av aspektorientering; Det er en måte å introdusere tjenester på domenet uten å berøre koden uten å bryte mot regelen med klare gamle objekter. Det er andre tilnærminger, for eksempel å skifte avhengighetene mellom tjenester og domenet til kontrolleren, men aspektorientert programmering er langt den mest elegante måten jeg kjenner. Jeg vil gjerne høre tankene dine om dette emnet!
Et godt rammeverk kan gi deg mye støtte i tillegg til de punktene jeg nevnte. For eksempel håndterer FLOW3 domenenobjektene i visningen med sin bemerkelsesverdig kule templerende motor som heter Fluid. Skrive Fluid maler, når domenet er gjort, er så avslappende som en dag på stranden.
Denne artikkelen er bare en introduksjon til Domain Driven Design. Jeg har presentert noen av hovedkonseptene, men jeg må innrømme at det kan være vanskelig å forstå teorien alene. Jeg vil oppfordre deg til å prøve Domain Driven Design for deg selv i et ekte verdensprosjekt. Du opplever at domenekonseptene er veldig intuitive å bruke.
Jeg har blitt kastet i DDD som en fisk ute av vannet i et veldig stort ekstbase-prosjekt, uten mye forkunnskap om konseptene (extbase er et Domain Driven Design-rammeverk for bygningsutvidelser for CMS Typo3 og er basert på FLOW3). Det har utvidet mitt perspektiv på hvordan jeg tenker på programvareutforming, og jeg håper det vil utvide ditt også.