Jump to content
php.lv forumi

MVC, kur un ko


teiks

Recommended Posts

Jautājums ir izklāstīts http://stackoverflow.com/questions/29930944/should-i-put-file-handling-in-model

 

Īsti nav vēlmes rindas no ctrl action pārnest uz servisu etc., uzskatu, ka vien tas pats būtu, līdz ar to anti-patterns? Ja pieņem, ka biznesa vērtības reprezentē modelis (datus un saistītās uzvedības/darbības), tad, vai tas ir labs piegājiens tmp failu pārvietošanu, manipulēšanu risināt modelī (Domain Model)?

 

Pieminēju arī, ka base modeļi FW-kos ir ORM/AR patterni. Cik valīdi ir Business Model-im mantot šādu base modeli? Ir labs veids kā tas tiek atdalīts?

Edited by teiks
Link to comment
Share on other sites

Es strukturēju sekojoši:

 

1. Repository klases - klases, kas sazinās ar db vai jebkādu citu datu resursu (api), atgriež objektus (ActiveRecord, ORM, whatever). Te nekādas loģikas nav, tupas datu saglabāšanas, atlasīšanas, dzēšanas
2. Model klases - ORM/ActiveRecord klases, kas satur tikai kolonnu definīcijas, utt. NEKĀDA loģika šeit netiek rakstīta. Tikai elementāras lietas, peimēram, metode getFullName() nas atgriež $this->name . ' '. $this->surname;

3. Library klases - klases kas darbojas ar repositorijiem un satur visu biznesa loģiku (piem, addMoney($userId, $amount) metode atlasītu useri no repositorija, pārbaudītu vai viņš drīkst saņemt naudu, pieskaitītu naudu makam un izsauktu repositorija metodi, kas veic saglabāšanu.

 

Kontrolieri sauc tikai library metodes, nekādā gadījumā uz savu galvu nesauc modeļu saglabāšanas utt, jo tas viss notiek caur librarijiem -> repositorijiem.

 

Attiecīgi šādu piegājienu viegli sanāk notestēt, jo atliek vien nomockot repostitoriju un iebarot viņu Library klasē. Testējam library klases. Izmantojam Dependency Injection lai padotu librarijiem repositorijus.

Link to comment
Share on other sites

Manuprāt, tu esi pazudis tulkojumā. Mēģināšu precizēt:

  • Kontrolieris - tas, pamatā, ir serviss, kas deleģē uzdevumus starp citiem servisiem - kā tieši tu organizē deleģāciju ir cits jautājums. Parasti, pats kontrolieris neko pats par sevi nedara, t.i. tevis minētajā piemēra, kontrolieris saņemtu Request, jeb informāciju, ka ir saņemts fails, nodotu faila darbības kādam servisam un no servisa atgriezto atbildi atdotu viewam, jeb skatam;
  • Modelis - par modeļiem parasti sauc datubāzes entitijas, jeb objektus, kas reprezentē ierakstus datubāzē (taču ne vienmēr - konkrētajā kontekstā gan). Modeļi parasti ir 2 veidu:
    • Smart entity: modelis, kas pats atbild par sevis glabāšanu un ir pašpietiekams - t.i. var veikt vienkāršas darbības pret saviem datiem (piem, no title izveidot slug utt.), spēj komunicēt ar ORM utt.
    • Simple entity: modelis, kurš vienkārši glabā vērtības bet nesatur praktiski nekādu biznesa loģiku. Skat. doctrine entity. 
  • Domēna modelis: ar ORM un datubāzi maz saistīts, abstrakts termins. Domēna modelis ir veids, kā organizēt un veidot arhitektūru. ORM modelis var būt domēna modeļa daļa. Biznesa loģika, servisu loģika un DB abstrakcija ir domēna modeļa daļas. Domēna modelis nav kaut kāds objekts vai kaut kas tamlīdzīgs, tas ir organizācijas veids, līdzīgi ka MVC.

Un kā mēs varam atrisināt tevis minēto piemēru:

<?php

class ImageUploadController
{
    public function uploadAction(
        Request $request,
        ImageUploadService $imageUploadService
    )
    {
        $error = $entity = false;

        if ($request->has('uploaded_file')) {
            try {
                $entity = $imageUploadService->handleUpload($request->get('uploaded_file'));

            } catch (ImageUploadException $e) {
                $error = $e;
            }
        }
        $this->renderView('someview', [
            'entity' => $entity,
            'error' => $error
        ]);
    }
}

class ImageUploadService
{
    private $orm;

    public function __construct(ORM $orm)
    {
        $this->orm = $orm;
    }

    public function handleUpload($fileInfo)
    {
        $this->validateUpload($fileInfo);
        $this->moveFile($fileInfo);
        return $this->createFileRecord($fileInfo);
    }

    private function validateUpload($fileInfo)
    {
        /** ... Validation logic */
    }

    private function moveFile($fileInfo)
    {
        /** ... Moving file in FS logic */
    }

    private function createFileRecord($fileInfo)
    {
        $record = new ImageEntity();
        /** Set data to entity etc */
        $this->orm->save($record);
        return $record;
    }
}

class ImageEntity
{
    private $id;
    private $uploadDate;
    private $originalName;
    /** getters, setters, etc. **/
}

Konkrētajā gadījunā, visas šīs klases ir daļa no attēla augšupielādes domēna modeļa.

Edited by F3llony
Link to comment
Share on other sites

Pazudis visnotaļ, jau 5cas dienas. :| sry, brainfarted a bit, es biju domājis businesss model.

Tāds termins, kā biznesa modelis programmēšanā nepastāv. Ja tu domāji biznesa loģiku, tad biznesa loģikas implementācija ir serviss - klases, un objekti kas satur biznesa loģikas implementāciju. 

Link to comment
Share on other sites

well, atļaušos nepiekrist. Piemēram, Image modelis kā tāds biznesam ir konkrēta entītija. Biznes skaidri definē ko nozīmē būt par Image. Kādi biznesa rūļi, tā uzvedība. Ja nemaldos, Martin Flower deva servisam pavisam citu lomu. Secinu, viss biznes grozās ap konkrētu modeli. Tas šķiet ne-aplams koncepts, jo ja paskatās uz šo modeli, ir pavisam skadirs kas tas ir. Arī programmētājs no malas līdz ar to būs bez pārpratumiem, jo piemēram, Image kā entītija nevar pastāvēt bez faila un ar nevalīdiem rūļiem, image var darīt to un šo. No tā izriet, ka nemaz patvaļīgi nedrīkst izveidot modeli, kuram netiek piedāvāts fails.

 

Okay, fine, kaut kur applikācijas dzīlēs ir servis, kas dara kaut ko. Kāda iespēja, ka applikāciju nepārzinošs, rakstnieks meklēs servisu nevis "biznesa objektu" brīdī, kad biznes maina savas domas par Image, vai kādā citā mērā to ietekmē. Ceru, ka uzmudinu uz domas.

 

Es servisu izmantotu kā konkrētu vienumu, kas nevis veic dažādus biznesa lōģikas uzdevumus (vai jeb kādā veidā piedalās kādā procesēšanā/kalkulācijās), bet gan uztilizē konkrētas instances no domēna sajūdzot tās kopā. Servis, vārds ka tāds, man tieši ar to asociējas, tas servē kādu konkrētu būtību domēnā. ImageUploadService man simbolizē uzdevumu. uzdevumiem es veidotu komandas.

 

Šķiet, ka programmēšana in general ir dažādu principu/ētikas mikslis, jo var manīt dažādas interpretācijas. 

Link to comment
Share on other sites

Tu tagad samauci visu vienā maisā atkal. 

  • Bizness ne ap ko negrozās. Bizness definē prasības;
  • Ko tu sauc par biznesa modeli, patiesībā sauc "biznesa objekts" ala "dumb entity" ala "data transfer object" ala "anemic domain object", atkarībā no konteksta;

 

Okay, fine, kaut kur applikācijas dzīlēs ir servis, kas dara kaut ko. Kāda iespēja, ka applikāciju nepārzinošs, rakstnieks meklēs servisu nevis "biznesa objektu" brīdī, kad biznes maina savas domas par Image, vai kādā citā mērā to ietekmē. Ceru, ka uzmudinu uz domas.

Tu runā par kaut kādu smart entity un biznesa loģikas implementācijas hibrīdu. Cilvēki tā programmēja 2005. gadā. 

 

Un realitātē notiks tieši otrādi - tu dosies uz kontrolieri, kurš izmanto servisu, tad tu aiziesi uz servisu un viss būs ļoti skaidrs, kā manā piemērā. Ar tavu smart samačkātot entitiju viss būs vienā milzīgā blāķī un cilvēki tevi pamatoti ienīdīs - testēšana nebūs iespēja, kods būs cieši kopā, refaktorēšana būs sāpe un kaut ka modificēšana globalizētā biznesa loģikā arī. 

 

 

Es servisu izmantotu kā konkrētu vienumu, kas nevis veic dažādus biznesa lōģikas uzdevumus (vai jeb kādā veidā piedalās kādā procesēšanā/kalkulācijās), bet gan uztilizē konkrētas instances no domēna sajūdzot tās kopā. Servis, vārds ka tāds, man tieši ar to asociējas, tas servē kādu konkrētu būtību domēnā. ImageUploadService man simbolizē uzdevumu. uzdevumiem es veidotu komandas.

Nē. Un nebāz, lūdzu, konkrēta freimworka konceptus, šajā gadījumā, Laravel "komandas", kas ir tie paši servisi vienā maisā ar arhitektūras un programmēšanas konceptiem in general. 

 

Laravel command bus ir tā pati servisu kolekcija, kur katra komanda ir serviss. Serviss savukārt ir jebkas, kas dara kaut kādu konkrētu uzdevumu domēna zonā. Lai gan tik dziļi pieduroties mans piemērs augstāk arī nebija īsti pareizs - ImageUploadService būtu serviss, kas izmantotu ImageValidatorService, ImageEntityCreatorService un FileSystemAbstractionService, piemēra pēc.

 

 

Arī programmētājs no malas līdz ar to būs bez pārpratumiem, jo piemēram, Image kā entītija nevar pastāvēt bez faila un ar nevalīdiem rūļiem, image var darīt to un šo. No tā izriet, ka nemaz patvaļīgi nedrīkst izveidot modeli, kuram netiek piedāvāts fails.

Nē. Ja tu visu šo loģiku saliksi vienā maisā, tev būs entitija, kas ir pa 10k rindām. Un pat konceptuāli, entitija var pastāvēt ar visām vērtībām null, kā tukšs objekts - šajā gadījumā biznesa prasība veidojas pret pārliecību, ka entitija nevarētu būt bez image utml, bet tas ir validācijas, ne datu glabāšanas vai manipulācijas domēns - t.i. objektam, kura mērkis ir glabāt datus būtu jāvalidē konkrētās entitijas domēnā, bet citā "domain concern", aļa servisā. Šādi, mainot rules, tu mainīsi nevis pašu entitiju, bet gan validācijas servisu, kas pie reizes neietekmēs tavas vecās entitijas (pie dotas implementācijas).

 

 

Uhh, palagi. 

Link to comment
Share on other sites

Lasot SO jautājumu, rodas sajūta, ka cilvēks vienkārši DAUDZ PAR DAUDZ aizdomājas par tām lietām (i.e. patīk sarežģīt vienkāršas lietas). Vnk liec tās file handling metodes Image klasē un miers. Ar MVC or whatever tam nav nekāda sakara.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...