mvc opis. Prikladan pristup web razvoju: MVC model
Dobar dan, drage kolege. U ovom članku želio bih govoriti o svom analitičkom razumijevanju razlika između MVC, MVP i MVVM uzoraka. Na pisanje ovog članka potaknula me želja za razumijevanjem modernih pristupa razvoju velikog softvera i odgovarajućih arhitektonskih značajki. U trenutnoj fazi moje karijere nisam izravni programer, tako da članak može sadržavati pogreške, netočnosti i nesporazume. Zanima vas kako analitičari vide što programeri i arhitekti rade? Onda dobrodošli pod kat.
Linkovi Prvo s čime bih želio započeti su linkovi na vanjske materijale kojima sam se rukovodio u procesu pisanja ovog članka:Uvod U vrijeme kad je sunce jače sjalo i trava bila zelenija, tada je tim studenata, poput autora ovog članka, razvijao softver upisujući stotine redaka koda izravno u sučelje proizvoda. Ponekad su se za rad s podacima koristili servisi i upravitelji, a tada se rješenje dobivalo pomoću obrasca Document-View. Podrška ovakvog koda zahtijevala je enormne troškove, budući da je novog programera trebalo obučiti (kazati) koji je kod za što u proizvodu odgovoran, a ni o kakvom jediničnom testiranju nije bilo govora. Razvojni tim čine 4 osobe koje sjede u istoj prostoriji.
Vrijeme je prolazilo, poslovi su se mijenjali. Aplikacije koje su se razvijale postale su veće i složenije, od jednog kohezivnog razvojnog tima do mnogo različitih timova programera, arhitekata, stručnjaka za upotrebljivost, dizajnera i menadžera. Sada je svatko odgovoran za svoje područje: GUI, poslovna logika, komponente. Postojao je odjel za analizu, ispitivanje, arhitekturu. Trošak razvoja softvera porastao je stotine, pa čak i tisuće puta. Ovakav pristup razvoju zahtijeva stabilnu arhitekturu koja bi međusobno sinkronizirala različita funkcionalna područja proizvoda Uzorci S obzirom na cilj smanjenja troškova rada za razvoj složenog softvera, pretpostavimo da je potrebno koristiti gotova unificirana rješenja. Uostalom, uzorak radnji olakšava komunikaciju među programerima, omogućuje vam da se pozivate na dobro poznate konstrukcije i smanjuje broj pogrešaka.
Prema Wikipediji, uzorak (engleski design pattern) je ponovljivi arhitektonski dizajn, koji je rješenje dizajnerskog problema unutar nekog konteksta koji se često pojavljuje.
Počnimo s prvim glavnim – Model-View-Controller. MVC je temeljni obrazac koji je pronašao primjenu u mnogim tehnologijama, iznjedrio nove tehnologije i olakšava život programerima svaki dan.
MVC uzorak se prvi put pojavio u jeziku SmallTalk. Programeri su morali osmisliti arhitektonsko rješenje koje bi odvojilo grafičko sučelje od poslovne logike, a poslovnu logiku od podataka. Tako se u klasičnoj verziji MVC sastoji od tri dijela, po čemu je i dobio ime. Razmotrite ih:
Model Model se obično shvaća kao dio koji sadrži funkcionalnu poslovnu logiku aplikacije. Model mora biti potpuno neovisan o ostatku proizvoda. Sloj modela ne mora znati ništa o elementima dizajna i načinu na koji će biti prikazan. Postiže se rezultat koji vam omogućuje da promijenite prezentaciju podataka, kako se prikazuju, bez diranja samog modela.Model ima sljedeće karakteristike:
- Model je poslovna logika aplikacije;
- Model ima znanje o sebi i ne zna za kontrolere i poglede;
- Za neke projekte, model je samo sloj podataka (DAO, baza podataka, XML datoteka);
- Za druge projekte, model je upravitelj baze podataka, zbirka objekata ili jednostavno logika aplikacije;
Pogled ima sljedeće značajke:
- Pogled implementira prikaz podataka koji su na bilo koji način dobiveni iz modela;
- U nekim slučajevima pogled može imati kod koji implementira neku poslovnu logiku.
- Model-View-Controller
- Model-Pogled-Prezenter
- Model-View-View Model
Razmotrite i usporedite svaki od njih.
Model-Pogled-PrezenterOvaj pristup vam omogućuje stvaranje apstrakcije pogleda. Da biste to učinili, morate istaknuti sučelje pogleda s određenim skupom svojstava i metoda. Prezenter zauzvrat prima referencu za implementaciju sučelja, pretplaćuje se za pregled događaja i mijenja model na zahtjev.
Značajke prezentera:
- Pogled izravno komunicira s prezenterom pozivanjem odgovarajućih funkcija ili događaja na instanci prezentera;
- Presenter komunicira s Viewom pomoću posebnog sučelja koje implementira View;
- Jedna instanca izlagača povezana je s jednim pogledom.
Implementacija:
Svaki pogled mora implementirati odgovarajuće sučelje. Sučelje prikaza definira skup funkcija i događaja potrebnih za interakciju korisnika (na primjer, IView .ShowErrorMessage(string msg)). Prezenter mora imati referencu na implementaciju odgovarajućeg sučelja, koja se obično prosljeđuje u konstruktoru.
Logika prezentacije mora imati referencu na instancu izlagača. Svi događaji pogleda prosljeđuju se izlagaču na obradu i gotovo nikada njima ne upravlja logika pogleda (uključujući stvaranje drugih pogleda).
Primjer upotrebe: Windows Forms.
Model-View-View ModelOvaj vam pristup omogućuje povezivanje elemenata pogleda sa svojstvima i događajima modela Pogled. Može se tvrditi da svaki sloj ovog uzorka nije svjestan postojanja drugog sloja.
Značajke modela View:
- Dvosmjerna komunikacija uz prezentaciju;
- Model pogleda je apstrakcija pogleda. Obično znači da su svojstva pogleda ista kao svojstva pogleda/modela
- Model prikaza nema referencu na sučelje pogleda (IView). Promjenom stanja modela View automatski se mijenja pogled i obrnuto, jer se koristi mehanizam vezanja podataka (Bindings).
- Jedna instanca modela pogleda povezana je s jednim zaslonom.
Implementacija:
Kada koristite ovaj uzorak, pogled ne implementira odgovarajuće sučelje (IView).
Pogled mora imati poveznicu na izvor podataka (DataContex), što je u ovom slučaju View model. Elementi pogleda vezani su (Bind) na odgovarajuća svojstva i događaje modela pogleda.
Zauzvrat, model View implementira posebno sučelje koje se koristi za automatsko ažuriranje elemenata prikaza. Primjer takvog sučelja u WPF-u bio bi INotifyPropertyChanged.
Primjer upotrebe: WPF
Model-View-ControllerGlavna ideja ovog uzorka je da i kontroler i pogled ovise o modelu, ali model ni na koji način ne ovisi o ove dvije komponente.
Značajke kontrolera
- Kontroler određuje koji pogled treba prikazati u tom trenutku;
- Događaji prikaza mogu utjecati samo na kontroler. Kontroler može utjecati na model i definirati drugačiji prikaz.
- Moguće je imati više pogleda za samo jedan kontroler;
Implementacija:
Kontroler izvana presreće događaj i, u skladu s logikom ugrađenom u njega, reagira na taj događaj promjenom Modela pozivanjem odgovarajuće metode. Nakon promjene, Model koristi događaj koji je promijenio, a svi View događaji pretplaćeni na ovaj događaj, nakon što ga prime, obraćaju se Modelu za ažurirane podatke, nakon čega se prikazuju.
Slučaj upotrebe: MVC ASP.NET
Sažetak Implementacija MVVM i MVP obrazaca na prvi pogled izgleda prilično jednostavno i slično. Međutim, za MVVM, vezanje pogleda na View-model provodi se automatski, a za MVP je potrebno programiratiČini se da MVC ima više opcija za upravljanje prikazom Opća pravila za odabir uzorka u MVVM-u
- Koristi se u situaciji kada je vezanje podataka moguće bez potrebe za uvođenjem posebnih sučelja pogleda (tj. nema potrebe za implementacijom IView-a);
- Čest primjer je WPF tehnologija.
- Koristi se u situaciji kada povezivanje podataka nije moguće (ne možete koristiti Povezivanje);
- Uobičajen primjer je korištenje Windows Forms.
- Koristi se u situaciji kada komunikacija između prikaza i drugih dijelova aplikacije nije moguća (i ne možete koristiti MVVM ili MVP);
- Uobičajen slučaj upotrebe je ASP.NET MVC.
Hvala vam puno na vašem vremenu, ugodno čitanje!
SRC:
O'Reill. ActionScript 3.0 obrasci dizajna.
Poglavlje 12
Što je obrazac Model-View-Controller?
Model-View-Controller (MVC) je složeni uzorak ili višestruki uzorci koji zajedno rade na implementaciji složenih aplikacija. Ovaj uzorak se najčešće koristi za kreiranje aplikacijskih sučelja, a kao što naziv govori, sastoji se od tri elementa:
Model(model)
Sadrži podatke o aplikaciji i logiku za upravljanje stanjem te aplikacije
Izvođenje(Pogled)
Implementira korisničko sučelje i stanje aplikacije, vidljivo na ekranu
Kontrolor(Kontroler)
Rukuje radnjama korisnika koje utječu na stanje aplikacije.
Snaga MVC uzorka dolazi izravno iz odvajanja ova tri elementa kako bi se izbjeglo preklapanje područja odgovornosti svakog od njih. Pogledajmo za što je svaki od elemenata odgovoran.
Model
Model je odgovoran za upravljanje stanjem aplikacije. Logika aplikacije u modelu predstavljena je s dva važna zadatka: model odgovara na zahtjeve za stanje aplikacije i izvodi radnje kao odgovor na zahtjev za promjenom stanja.
Izvođenje
Pogled je izgled aplikacije. Korisnik komunicira s aplikacijom kroz View. Aplikacija može sadržavati više pogleda, koji mogu biti i ulazni i izlazni mehanizam. Na primjer, u prijenosnom digitalnom playeru kao što je iPod, zaslon uređaja bio bi View. Gumbi igrača također se smatraju Pogledom. Zaslon prikazuje naslov i trajanje pjesme, omot albuma i druge stvari koje su povezane s trenutnim stanjem uređaja. Pogled ne mora biti vidljiv. U prijenosnom playeru, glazba koja se reproducira u slušalicama također je izvedba. Na primjer, pritisak na tipku može izazvati neki zvučni odgovor u obliku klika u slušalicama. Promjene glasnoće također se odražavaju na izlaznom audio kanalu. Zvučna povratna informacija povezana je sa stanjem aplikacije.
Kontrolor
Iako pojam kontroler implicitno podrazumijeva sučelje preko kojeg se kontrolira aplikacija, u MVC uzorku kontroler ne sadrži elemente korisničkog sučelja. Kao što je gore spomenuto, elementi korisničkog sučelja koji pružaju unos pripadaju komponenti View. Upravljač, s druge strane, određuje kako Views reagira na korisnički unos.
Recimo da naš digitalni player ima gumbe Glasnije I Miran u Pogledu. Glasnoća zvuka je varijabla stanja. Model će pratiti ovu varijablu kako bi promijenio vrijednost ove varijable u skladu s logikom aplikacije. Ako je vrijednost glasnoće zvuka stupnjevana od 0 do 10, kontroler će odrediti koliko će povećati ili smanjiti zvuk kada se jedan od ovih gumba pritisne jednom. Ponašanje može reći Modelu da poveća glasnoću za 0,5, ili za 0,1, ili bilo koju drugu vrijednost koja je programski navedena. U tom smislu, kontroleri su specifičnosti implementacije koje definiraju kako će aplikacija odgovoriti na korisnički unos.
Iako svaki element u MVC trijadi ima zasebno i jedinstveno područje odgovornosti, oni ne funkcioniraju izolirano. Zapravo, da bi se sačinio MVC obrazac, svaki element mora komunicirati s ostalima. Što to znači, razmotrit ćemo u nastavku.
Interakcija MVC elemenata
Svaki element u MVC uzorku komunicira s ostalima na vrlo specifične načine. Komunikacija se provodi nizom događaja koji se obično pokreću interakcijom korisnika s aplikacijom. Redoslijed događaja izgleda ovako:
Ovo je vrlo jednostavan dijagram interakcije MVC elemenata. U nekim slučajevima, kontroler može jednostavno reći Viewu da se promijeni. Ovo je jedini slučaj u kojem promjene Pogleda postaju neophodne zbog akcije korisnika i ne zahtijevaju promjene Modela, već samo rezultiraju samo vizualnim promjenama. Na primjer, razmislite o tome kako korisnik odabire pjesmu na digitalnom playeru. Odabire pjesmu s popisa tipkama za pomicanje. Pogled treba reći kontroleru da su pritisnute tipke za pomicanje gore ili pomicanje prema dolje, ali kontroler ne mora obavijestiti model. Izravno govori Viewu da pomiče popis pjesama u željenom smjeru. Takva radnja korisnika ne zahtijeva izmjene Modela. Međutim, kada korisnik odabere pjesmu s popisa i počne je reproducirati, kontroler će promijeniti model kako bi odražavao tu promjenu u vrijednosti pjesme koja se trenutno reproducira.
Osim toga, promjene u modelu nisu uvijek potaknute radnjama korisnika. Model se može ažurirati na temelju određenih događaja. Uzmimo, na primjer, indikator cijene dionica. Model nije povezan s trenutnom vrijednošću dionica. Međutim, sama cijena se mijenja i Model može postaviti mjerač vremena za primanje periodičnih ažuriranja s web usluge. A onda, svaki put kada Model ažurira svoje podatke o cijeni dionice, obavijestit će View da se stanje promijenilo.
Još jedna značajka MVC obrasca je da svaki takav model može imati više od jednog pogleda pridruženog sebi. Na primjer, u našem prijenosnom playeru, postavke glasnoće mogu se prikazati na zaslonu pomoću mjerača razine. Osim toga, razina zvuka na audio izlazu korelira s glasnoćom zvuka u slušalicama. I zaslon i zvuk u slušalicama su prikazi statusa uređaja.
Pogledajte sliku 12-1 i obratite pažnju na smjer strelica. Oni pokazuju tko inicira interakciju između elemenata. Da bi jedan MVC element mogao komunicirati s drugim, mora znati za njega i posjedovati referencu na taj element.
Zamislite Model, View i Controller kao tri različite klase. Pogledajmo koje klase moraju imati reference na druge klase:
Izvođenje
Mora imati referencu i na Model i na Kontrolora
Kontrolor
Mora posjedovati referencu na Model
Započeli smo izjavom da je MVC složeni uzorak koji kombinira više uzoraka. Sigurno se pitate koji su uzorci uključeni u ovaj složeni uzorak. Ili, točnije, kako ih se može prikazati? Glavna prednost korištenja MVC obrasca je mogućnost da se on raščlani na tri sastavna elementa. To nam omogućuje povezivanje više pogleda s istim modelom, zamjenu modela i kontrolera bez utjecaja na druge elemente. Ali neki elementi u MVC trijadi moraju održavati reference na druge elemente, te također podržavati aktivnu komunikaciju među njima. Kako možemo nazvati takvu podjelu? To ima veze s obrascima promatrača, strategije i kompozita.
Ubacivanje uzoraka u MVC
Kao što smo već vidjeli, model se može povezati s više pogleda. U MVC-u, model mora obavijestiti sve poglede povezane s njim o promjenama koje se događaju. Osim toga, to se mora učiniti bez poznavanja specifičnih pojedinosti o Pogledima, pa čak i bez znanja koliko se Pogleda treba promijeniti. Ovaj se zadatak najbolje postiže korištenjem implementacije uzorka preglednika (vidi Poglavlje 8).
Svaki model može imati više prikaza povezanih s njim. Slično tome, Views može biti složen, s višestrukim prozorima ili panelima koji sadrže druge elemente korisničkog sučelja. Na primjer, takvi elementi sučelja kao što su gumbi, tekstualna polja, popisi, klizači itd. mogu se grupirati u panel s karticama, a panel, pak, može biti dio prozora zajedno s drugim panelima. Svaki gumb ili grupa gumba može biti Pogled. Isto je i sa zbirkom tekstualnih polja. Čini se korisnim postupati s pločom ili prozorom koji sadrži zbirke jednostavnih prikaza na isti način na koji postupamo s bilo kojim drugim prikazima. Ovo je mjesto gdje će nam korištenje uzorka povezivača uštedjeti mnogo truda (vidi Poglavlje 6). Zašto je implementacija uzorka povezivača toliko korisna u ovom kontekstu? Ako se pogledi mogu ugniježditi, što i jesu kada su stvoreni pomoću obrasca Composer, postupak ažuriranja je pojednostavljen. Događaj ažuriranja automatski će zaobići sve prikaze potomke. Stvaranje složenih prikaza postaje lakše kada nema potrebe za slanjem pojedinačnih poruka ažuriranja svakom ugniježđenom prikazu.
Pogledi ograničavaju svoju aktivnost samo na vanjski prikaz stanja Modela. Oni prosljeđuju događaje korisničkog sučelja kontroleru. Stoga je kontroler više algoritam za rukovanje korisničkim unosom u određenom prikazu. Takvo delegiranje sažima implementaciju načina na koji se određeni element prilagođenog elementa ponaša u slučaju promjene u Modelu. Možemo vrlo lako zamijeniti jedan kontroler za isti pogled kako bismo dobili drugačije ponašanje. Ovo je idealan kontekst za implementaciju obrasca strategije.
Primjer minimalističkog MVC uzorka
Ovaj jednostavan primjer prati pritiske tipki. Kada se pritisne sljedeća tipka, to uzrokuje promjenu modela i obavještava View da se ažurira. Prikaz koristi Flashov standardni izlazni prozor za postavljanje znakovnog koda koji je korisnik upisao u njega. Šifra znaka je numerička vrijednost znaka u tablici kodova trenutnog izgleda. Ovaj primjer objašnjava kako su uzorci preglednika, strategije i graditelja integrirani u MVC.
Model kao konkretan predmet u predlošku preglednika
Odnos između modela i pogleda je odnos između predmeta i preglednika (vidi Poglavlje 8). Model mora implementirati sučelje Subject, koje je dio obrasca Browser. Srećom, ActionScript 3.0 ima ugrađene klase koje već implementiraju ovo načelo, koristeći ActionScript model događaja za obavještavanje preglednika o promjenama.
Klasa EventDispatcher u ActionScriptu 3.0
Klasa EventDispatcher opremljena je sučeljem IEventDispatcher. Zajedno s drugim metodama, sučelje IEventDispatcher definira sljedeće metode koje su potrebne za predmet u predlošku preglednika. (Pogledajte AS3 dokumentaciju za detalje o svim parametrima metode).
addEventListener(tip:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false) :void removeEventListener(type:String, listener:Function, useCapture:Boolean = false) :void dispatchEvent( događaj:Događaj) :Booleov
Kako bi model djelovao kao konkretni subjekt u uzorku preglednika, morate implementirati sučelje IEventDispatcher. Međutim, najlakši način da određena prilagođena klasa dobije mogućnost distribucije događaja je naslijeđivanje od klase EventDispatcher.
Preglednik registrira metode slušatelja za primanje obavijesti od EventDispatcher objekata pomoću metode addEventListener().
Model
Naš model pohranjuje šifru znaka koja odgovara pritisnutoj tipki u svojstvu. Morate implementirati postavljač i dobivač kako biste omogućili View i Controlleru pristup i promjenu ovog svojstva. Definirajmo za naš model (primjer 12-1).
Primjer 12-1. IModel.as
paket ( import flash.events .* ; javno sučelje IModel proširuje IEventDispatcher ( funkcija setKey(key :uint) :void ; funkcija getKey() :uint; ) )
Sučelje IModel, prikazano u primjeru 12-1, proširuje sučelje IEventDispatcher i definira nekoliko metoda za čitanje i postavljanje znakovnog koda posljednje pritisnute tipke. Budući da sučelje IModel proširuje IEventDispatcher, svaka klasa koja ga implementira mora implementirati sve metode definirane u oba sučelja. Klasa Model prikazana u primjeru 12-2 implementira sučelje IModel.
Primjer 12-2. Model.kao
package ( import flash.events .* ; javna klasa Model proširuje EventDispatcher implementira IModel ( private var lastKeyPressed:uint=0 ; javna funkcija setKey(key :uint) :void ( this .lastKeyPressed =key ; dispatchEvent(new Event(Event.CHANGE) ) ) ; // događaj propagira ) javna funkcija getKey() :uint ( return lastKeyPressed; ) ) )
Klasa Model proširuje klasu EventDispatcher, koja već implementira sučelje IEventDispatcher. Imajte na umu da se funkcija dispatchEvent() poziva unutar metode setKey(). Šalje događaj CHANGE svim registriranim preglednicima čim se promijeni vrijednost lastKeyPressed unutar metode setKey().
Kontrolor kao konkretna strategija u predlošku strategije.
Odnos između kontrolera i pogleda može se predstaviti kao strategija i kontekst u obrascu strategije. Svaki kontroler bit će posebna strategija koja implementira traženo ponašanje unutar okvira sučelja strategije.
Kontrolor
U našem minimalističkom primjeru, ponašanje koje se zahtijeva od kontrolera je samo prihvaćanje događaja pritiska tipke. IKeyboardInputHandler je strateško sučelje (Primjer 12-3) gdje je definirana jedna metoda keyPressHandler().
Primjer 12-3. IKeyboardInputHandler.as
paket ( import flash.events .* ; javno sučelje IKeyboardInputHandler ( function keyPressHandler(event:KeyboardEvent) :void ; ) )
Konkretni kontroler bila bi klasa kontrolera (primjer 12-4), koja implementira sučelje IKeyboardInputHandler.
Primjer 12-4. Kontrolor.as
paket ( import flash.events .* ; javna klasa Controller implementira IKeyboardInputHandler ( private var model:IModel; javna funkcija Controller(aModel:IModel) ( this .model =aModel; ) javna funkcija keyPressHandler(event:KeyboardEvent) :void ( model. setKey (event.charCode); // promjena modela ) ) )
Imajte na umu da kontroler ima konstruktor koji uzima instancu modela kao parametar. Ovo je neophodno kako bi kontroler mogao komunicirati s modelom, kao što je prikazano na slici 12-1. Stoga je potrebno pohraniti referencu na Model.
Metoda keyPressHandler() uzima događaj korisničkog sučelja (u ovom slučaju, KeyboardEvent) kao parametar i zatim odlučuje kako njime postupiti. U našem primjeru, jednostavno postavlja kod pritisnute tipke u modelu.
Prikaz kao konkretni preglednik u predlošku preglednika i kontekst u predlošku strategije
Pogled je možda najsloženiji element u MVC uzorku. On igra ulogu integrirajućeg dijela u implementaciji obrazaca preglednika i strategije, što čini temelj njegovog odnosa s modelom i kontrolerom. Klasa View prikazana u ispisu 12-5 implementira View u minimalističkom primjeru.
Primjer 12-5. Pogled.kao
paket ( import flash.events .* ; import flash.display .* ; public class View ( private var model:IModel; private var controller:IKeyboardInputHandler; public function View(aModel:IModel,oController:IKeyboardInputHandler,target :Stage) ( ovo .model =aModel; ovaj .controller =oController; // pretplaćuje se na primanje obavijesti od modela model.addEventListener (Event.CHANGE ,this .update ) ; // pretplaćuje se na primanje pritisaka tipki od ciljne scene .addEventListener (KeyboardEvent.KEY_DOWN, this .onKeyPress ) ; ) privatna funkcija update(event:Event) :void ( // dobivanje podataka iz modela i ažuriranje prikaza prikaza (model.getKey () ) ; ) privatna funkcija onKeyPress(event:KeyboardEvent) :void ( / / obrada se prosljeđuje kontroleru (strategija) za obradu controller.keyPressHandler (događaj) ; ) ) )
Pogledu su potrebne i reference modela i kontrolera kako bi mogao s njima komunicirati, kao što je prikazano na slici 12-1. I instanca Modela i instanca Controllera prosljeđuju se Viewu u njegovom konstruktoru. Osim toga, View u našem primjeru treba referencu na Stage kako bi se registrirao kao primatelj događaja pritiska tipke.
Osim crtanja korisničkog sučelja, klasa View obavlja još nekoliko važnih zadataka. Registrira se s modelom za primanje događaja ažuriranja i delegira kontroleru za rukovanje korisničkim unosom. U našem primjeru, Pogled nema vanjsku vidljivu prisutnost na sceni, ali prikazuje stanje modela u izlaznom prozoru. Treba primiti događaj pritiska tipke i registrirati metodu onKeyPress() da primi događaj KEY_DOWN sa scene. Drugi zadatak je registracija metode slušača update() za primanje događaja CHANGE iz modela. Kada se primi obavijest o promjeni, metoda update() čita kod zadnje pritisnute tipke iz modela i ispisuje ga u izlazni prozor pomoću funkcije trace().
Izgradnja MVC trijade
Razmotrili smo implementaciju svakog od tri dijela MVC uzorka zasebno. Međutim, mora postojati klijent koji će inicijalizirati svaki element i izgraditi MVC model. Zapravo, neće biti složene konstrukcije - sve što treba učiniti već je učinjeno prilikom pisanja klasa Model, View i Controller. Primjer 12-6 pruža klasu Flash dokumenta koja ilustrira elemente MVC-a.
Primjer 12-6. Main.as (glavna klasa minimalističkog primjera)
paket ( import flash.display .* ; import flash.events .* ; /** * Glavna klasa * @ svrha: klasa dokumenta za film */ javna klasa Main proširuje Sprite ( javna funkcija Main() ( var model:IModel=new Model ; var controller:IKeyboardInputHandler=new Controller(model) ; var view:View=new View(model,controller,this .stage) ; ) ) )
Nakon što se model, kontroler i pogled inicijaliziraju, oni će međusobno komunicirati i početi raditi. Pritiskom na tipku na tipkovnici prikazat će se odgovarajući kod znaka u izlaznom prozoru.
Morate onemogućiti prečace za testiranje pritisaka na tipke. U suprotnom će Flash korisničko sučelje presresti događaje pritiskanja tipki koje odgovaraju prečacima. Kako biste onemogućili tipkovničke prečace, odaberite Onemogući tipkovničke prečace iz izbornika Kontrola dok se videozapis prikazuje.
Imajte na umu da se instanca modela prosljeđuje kontroleru. Slično, instance modela i kontrolera prosljeđuju se u prikaz. Možemo jednostavno zamijeniti postojeći model i kontroler s drugima, sve dok implementiraju sučelja IModel i IKeyboardInputHandler. Dodatni pogledi također se mogu bezbolno dodati izravno u odnos Subjekt-Gledatelj između modela i prikaza. Model ne zna ništa o Pogledima, budući da je na Pogledu da se registrira kao slušatelj za obavijesti o promjenama Modela. Ovo je veliki plus MVC uzorka; Model, View i Controller su odvojeni, labavo povezani, što daje fleksibilnost u njihovoj uporabi.
Ugniježđeni prikazi i čvorovi predložaka
Podsjetimo se da je Pogled možda najsloženiji element u MVC trijadi, jer je u MVC kontekstu uključen iu implementaciju obrasca preglednika i strategije. Naši View elementi mogu biti složeniji jer mogu implementirati treći obrazac, Layoutr (pogledajte primjere Layoutr uzorka u 6. poglavlju). Implementacija pogleda kao elemenata predloška Composite vam omogućuje da se nosite sa složenim korisničkim sučeljima koja sadrže više pogleda. Ugniježđeni pogledi donose neke prednosti procesu ažuriranja korisničkog sučelja jer se ažuriranja mogu širiti duž grana strukturalnog stabla kompozitnog pogleda. Composite Views također može dodavati i uklanjati ugniježđene Views na temelju ponašanja aplikacije i korisničkih postavki. Dobar primjer složenog sučelja je ploča Properties Inspector u Flash autorskom okruženju. Sadržaj Properties Inspectora osjetljiv je na kontekst, a elementi korisničkog sučelja pojavljuju se i nestaju ovisno o tome koji je objekt odabran u sceni.
Komponentni i kompozitni prikaz
Prvi korak je stvoriti komponente i složene klase za View. Ove klase moraju biti deklarirane kao apstraktne, moraju biti podklase i ne smiju se instancirati, kao što je prikazano u primjeru 12-7.
Primjer 12-7. ComponentView.as
paket ( import flash.errors .IllegalOperationError ; import flash.events .Event ; import flash.display .Sprite ; javna klasa ComponentView proširuje Sprite ( ( protected var model:Object ; protected var controller:Object ; javna funkcija ComponentView(aModel:Object, aController:Object =null ) ( this .model =aModel; this .controller =aController; ) javna funkcija add (c:ComponentView) :void ( throw new IllegalOperationError("operacija dodavanja nije podržana" ) ; ) javna funkcija remove(c: ComponentView) :void (baci novu IllegalOperationError("operacija uklanjanja nije podržana" ) ; ) javna funkcija getChild(n:int ) :ComponentView ( baci novu IllegalOperationError("operacija getChild nije podržana" ) ; vrati null ; ) // ABSTRAKTNA metoda( mora se nadjačati u klasi potomku) javna funkcija update(event:Event=null ) :void ( ) ) ) )
Klasa ComponentView iz primjera 12-7 definira apstraktno sučelje za Component View. Ovo je slično klasičnoj klasi komponenti iz poglavlja 6, ali s nekoliko ključnih razlika. Klasa ComponentView sadrži referencu na model i pogled i sadrži konstruktor. Ne rukuju svi pogledi korisničkim unosom, a komponentni pogled može se konstruirati jednostavnim prosljeđivanjem instance modela. Stoga je parametar aController u konstruktoru prema zadanim postavkama null. Također imajte na umu da je klasa ComponentView izvedena iz klase Sprite. Ovo ima smisla budući da većina prikaza crta korisničko sučelje na pozornici. Možemo koristiti svojstva i metode implementirane u klasi Sprite za crtanje i dodavanje objekata na popis za prikaz.
Metoda update() mora se ponašati kao apstraktna metoda. Podređeni pogledi koji su potomci ComponentViewa moraju nadjačati i implementirati metodu update() kako bi mogli ažurirati svoj dio korisničkog sučelja. Iz tog razloga, metodi se prosljeđuje parametar tipa Event. Ovaj je parametar također postavljen na null prema zadanim postavkama, što vam omogućuje pozivanje update() bez prosljeđivanja događaja kao parametra. Ovaj je pristup koristan kada je inicijalno prikazano korisničko sučelje u zadanom stanju, a naš sljedeći primjer to ilustrira.
Klasa CompositeView proširuje ComponentView i nadjačava metode koje su odgovorne za podređene prikaze.
Primjer 12-8. CompositeView.as
package ( import flash.events .Event ; // ABSTRACT class (morate ga naslijediti bez stvaranja instance ove klase) public class CompositeView extends ComponentView ( private var aChildren:Array ; public function CompositeView(aModel:Object ,aController: Object =null ) ( super (aModel,aController) ; this .aChildren =new Array ; ) override public function add (c:ComponentView) :void ( aChildren.push (c) ; ) override public function update(event:Event=null ) :void ( za svaki (var c:ComponentView u aChildren) ( c.update (event) ; ) ) ) )
Obratite pozornost na funkciju nadjačavanja update() klase CompositeView u primjeru 12-8. Poziva metodu ažuriranja na svim podređenim klasama. Stoga će pozivanje funkcije update() u korijenu strukture kompozitnog prikaza proširiti ažuriranje kroz strukturu i preći stablo komponente, ažurirajući sve poglede. Proširimo klase CompositeView i ComponentView i stvorimo strukturu View da vidimo kako funkcionira.
Mnogi ljudi počinju pisati projekt da rade s jednim zadatkom, ne implicirajući da može prerasti u višekorisnički sustav upravljanja, recimo, sadržajem ili, ne daj Bože, produkcijom. I sve se čini super i cool, sve radi dok ne počnete shvaćati da se kod koji je napisan sastoji isključivo od štaka i tvrdog koda. Kod je pomiješan s izgledom, zahtjevima i štakama, ponekad čak i nečitljiv. Pojavljuje se hitan problem: kada dodajete nove značajke, morate se dugo petljati s ovim kodom, prisjećajući se "što je tamo napisano?" i proklinjite sebe u prošlosti.Možda ste čak čuli za uzorke dizajna i čak prelistali ove sjajne knjige:
- E. Gamma, R. Helm, R. Johnson, J. Vlissides “Tehnike objektno orijentiranog dizajna. Dizajn uzorci";
- M. Fowler "Arhitektura poslovnih softverskih aplikacija".
Predstavljeni članak bit će koristan prvenstveno početnicima. U svakom slučaju, nadam se da ćete za nekoliko sati moći steći ideju o implementaciji MVC obrasca koji je u osnovi svih modernih web okvira, kao i dobiti “hranu” za daljnje razmišljanje o “ kako to učiniti". Na kraju članka nalazi se izbor korisnih poveznica koje će vam također pomoći da shvatite od čega se sastoje web okviri (osim MVC) i kako funkcioniraju.
Očvrsli PHP programeri vjerojatno neće pronaći nešto novo za sebe u ovom članku, ali njihovi komentari i komentari na glavni tekst bili bi od velike pomoći! Jer bez teorije ne može praksa, a bez prakse je teorija beskorisna, onda će prvo biti malo teorije, a onda ćemo prijeći na praksu. Ako ste već upoznati s konceptom MVC-a, možete preskočiti teorijski dio i prijeći ravno na praksu.
1. Teorija MVC uzorak opisuje jednostavan način za izgradnju strukture aplikacije koja ima za cilj odvojiti poslovnu logiku od korisničkog sučelja. Kao rezultat toga, aplikaciju je lakše skalirati, testirati, održavati i, naravno, implementirati.Razmotrite konceptualnu shemu MVC predloška (po mom mišljenju, ovo je najuspješnija shema od onih koje sam vidio):
U MVC arhitekturi, model osigurava podatke i pravila poslovne logike, pogled je odgovoran za korisničko sučelje, a kontroler osigurava interakciju između modela i pogleda.
Tipični tijek rada MVC aplikacije može se opisati na sljedeći način:
Ovo prikazuje prikaz, recimo, glavne stranice web mjesta.
koji npr. sadrži pozive modelu koji čitaju informacije iz baze podataka.
Model ne bi trebao izravno komunicirati s korisnikom. Sve varijable koje se odnose na zahtjev korisnika moraju se obraditi u kontroleru.
Model ne bi trebao generirati HTML ili drugi kod za renderiranje, koji se može mijenjati ovisno o potrebama korisnika. Takvim kodom treba rukovati u pogledima.
Isti model npr.: model autentifikacije korisnika može se koristiti i u korisničkom i u administrativnom dijelu aplikacije. U ovom slučaju, možete premjestiti zajednički kod u zasebnu klasu i naslijediti od nje, definirajući metode specifične za podaplikacije u nasljednicima.
Pogled - koristi se za postavljanje vanjskog prikaza podataka primljenih od kontrolera i modela.
Pogledi sadrže HTML oznake i male umetke PHP koda za indeksiranje, oblikovanje i prikaz podataka.
Ne bi trebao izravno pristupiti bazi podataka. Modeli bi to trebali raditi.
Ne bi trebalo raditi s podacima primljenim na zahtjev korisnika. Ovaj zadatak mora izvršiti upravljač.
Može izravno pristupiti svojstvima i metodama kontrolera ili modela kako bi dobio podatke spremne za izlaz.
Pogledi se obično dijele na zajednički predložak koji sadrži oznake zajedničke za sve stranice (na primjer, zaglavlje i podnožje) i dijelove predloška koji se koriste za prikaz izlaznih podataka iz modela ili prikaz obrazaca za unos podataka.
Kontroler je poveznica koja povezuje modele, prikaze i druge komponente u radnu aplikaciju. Kontrolor je odgovoran za obradu zahtjeva korisnika. Kontroler ne smije sadržavati SQL upite. Bolje ih je držati u modelima. Kontroler ne smije sadržavati HTML ili druge oznake. Zaslužuje da se iznese na vidjelo.
U dobro dizajniranoj MVC aplikaciji, kontroleri su obično vrlo tanki i sadrže samo nekoliko desetaka redaka koda. Što se ne može reći o Stupid Fat Controllers (SFC) u CMS Joomla. Logika kontrolera prilično je tipična i većina je izdvojena u osnovnim klasama.
Modeli su, s druge strane, vrlo debeli i sadrže većinu koda povezanog s obradom podataka. struktura podataka i poslovna logika koju sadrži obično su prilično specifični za određenu aplikaciju.
Nadam se da ste već primijetili da različite stranice mogu imati potpuno različite formate za izradu adresne trake. Svaki format može predstavljati arhitekturu web aplikacije. Iako to nije uvijek slučaj, u većini slučajeva to je jasna činjenica.
Razmotrite dvije opcije za adresnu traku, koje prikazuju neki tekst i korisnički profil.
Približan kod obrade u ovom slučaju:
switch($_GET["action"]) ( case "about" : require_once("about.php"); // prijelom stranice "O nama"; case "contacts" : require_once("contacts.php"); // prekid stranice "Kontakti"; case "feedback" : require_once("feedback.php"); // prekid stranice "Feedback"; zadano: require_once("page404.php"); // prekid stranice "404"; )
Mislim da su to već učinili gotovo svi.
Koristeći URL mehanizam za usmjeravanje, možete konfigurirati svoju aplikaciju da prihvaća zahtjeve poput ovog za prikaz istih informacija:
http://www.example.com/contacts/feedback
Ovdje su kontakti kontroler, a povratna informacija je metoda kontrolera kontakata koja prikazuje obrazac za povratne informacije, i tako dalje. Ovom pitanju ćemo se vratiti u praktičnom dijelu.
Također je vrijedno znati da usmjerivači mnogih web okvira omogućuju stvaranje proizvoljnih URL ruta (navedite što svaki dio URL-a znači) i pravila za njihovu obradu.
Sada imamo dovoljno teorijskog znanja da prijeđemo na praksu.
Gledajući unaprijed, reći ću da će osnovne klase Model, View i Controller biti pohranjene u osnovnoj mapi.
Njihova djeca bit će pohranjena u direktorije kontrolera, modela i prikaza. Datoteka index.php je ulazna točka u aplikaciju. Datoteka bootstrap.php pokreće učitavanje aplikacije, uključujući sve potrebne module itd.
Idemo redom; otvorite datoteku index.php i ispunite je sljedećim kodom:
ini_set("pogreške_prikaza", 1); require_once "aplikacija/bootstrap.php";
Ovdje ne bi trebalo biti pitanja.
Zatim, skočimo ravno na datoteku bootstrap.php:
require_once "core/model.php"; require_once "core/view.php"; require_once "core/controller.php"; require_once "core/route.php"; Ruta::start(); // pokretanje rutera
Prva tri retka će sadržavati trenutno nepostojeće kernel datoteke. Posljednji redovi uključuju datoteku s klasom usmjerivača i pokreću je za izvođenje pozivanjem metode statičkog pokretanja.
RewriteEngine On RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php [L]
Ovaj kod će preusmjeriti obradu svih stranica na index.php , što je ono što nam treba. Sjećate se da smo u prvom dijelu govorili o Front Controlleru?!
Usmjeravanje ćemo smjestiti u zasebnu datoteku route.php u osnovnom direktoriju. U ovoj datoteci ćemo opisati klasu Route, koja će pokretati metode kontrolera, koji će zauzvrat generirati izgled stranica.
Sadržaj datoteke Route.php
klasa Ruta ( statička funkcija start() ( // zadani kontroler i akcija $controller_name = "Main"; $action_name = "index"; $routes = explode("/", $_SERVER["REQUEST_URI"]); // dobiti ime kontrolera if (!empty($routes)) ( $controller_name = $routes; ) // dobivanje naziva radnje if (!empty($routes)) ( $action_name = $routes; ) // dodavanje prefiksa $model_name = " Model_ ".$controller_name; $controller_name = "Controller_".$controller_name; $action_name = "action_".$action_name; // spojite datoteku s klasom modela (možda ne postoji datoteka modela) $model_file = strtolower($model_name ). ".php"; $model_path = "application/models/".$model_file; if(file_exists($model_path)) ( uključi "application/models/".$model_file; ) // spojite datoteku klase kontrolera $controller_file = strtolower ($controller_name).".php"; $controller_path = "application/controllers/".$controller_file; if(file_exists($controller_path)) ( uključi "aplikacija/controllers/".$controller_file; ) else ( /* bilo bi ispravno izbaciti iznimku ovdje, ali radi jednostavnosti odmah ćemo preusmjeriti na stranicu 404 */ Route::ErrorPage404(); ) // kreirati kontroler $controller = new $controller_name; $akcija = $akcija_name; if(method_exists($controller, $action)) ( // poziva radnju kontrolera $controller->$action(); ) else ( // također bi imalo više smisla izbaciti iznimku ovdje Route::ErrorPage404(); ) ) function ErrorPage404( ) ( $host = "http://".$_SERVER["HTTP_HOST"]."/"; header("HTTP/1.1 404 nije pronađen"); header("Status: 404 nije pronađen" ); zaglavlje(" Lokacija:".$host."404"); ) )
Napominjem da klasa implementira vrlo pojednostavljenu logiku (unatoč voluminoznom kodu) i možda čak ima sigurnosnih problema. To je učinjeno namjerno, jer. pisanje punopravne klase usmjeravanja zaslužuje barem poseban članak. Pogledajmo glavne točke...
Element globalnog polja $_SERVER["REQUEST_URI"] sadrži punu adresu na koju se korisnik prijavio.
Na primjer: example.ru/contacts/feedback
Korištenje funkcije eksplodirati adresa je podijeljena na komponente. Kao rezultat, dobivamo naziv kontrolera, za navedeni primjer, ovo je kontroler kontakti i naziv radnje, u našem slučaju - Povratne informacije.
Zatim se povezuje datoteka modela (model može nedostajati) i datoteka kontrolera, ako postoji, i na kraju, kreira se instanca kontrolera i ponovno se poziva akcija ako je opisana u klasi kontrolera.
Dakle, kada odete npr. na adresu:
primjer.com/portfolio
ili
primjer.com/portfolio/index
Usmjerivač će učiniti sljedeće:
primjer.com/ufo
tada će biti preusmjeren na stranicu 404:
primjer.com/404
Isto će se dogoditi ako korisnik pristupi radnji koja nije opisana u kontroleru.2.2. Povratak na implementaciju MVC-a. Idemo u mapu jezgre i dodamo još tri datoteke u datoteku route.php: model.php, view.php i controller.php
Dopustite mi da vas podsjetim da će sadržavati osnovne klase, koje ćemo sada početi pisati.
Sadržaj datoteke model.php
model klase ( javna funkcija get_data() ( ) )
Klasa modela sadrži jednu praznu metodu dohvaćanja podataka koja će biti nadjačana u klasama potomcima. Kada stvorimo klase potomke, sve će postati jasnije.
Sadržaj datoteke view.php
class View ( //public $template_view; // ovdje možete navesti zadani javni prikaz. function generate($content_view, $template_view, $data = null) ( /* if(is_array($data)) ( // pretvori niz elemente u varijable ekstrakt($data); ) */ uključi "application/views/".$template_view; ) )
Nije teško pogoditi da metoda generirati dizajniran da oblikuje pogled. U njega se prosljeđuju sljedeći parametri:
za prikaz sadržaja određene stranice.
U našem slučaju, opći predložak sadržavat će zaglavlje, izbornik, bočnu traku i podnožje, a sadržaj stranica bit će sadržan u zasebnom obliku. Opet, ovo je učinjeno radi jednostavnosti.
Sadržaj datoteke controller.php
klasa Controller ( javni $model; javni $view; funkcija __construct() ( $this->view = new View(); ) funkcija action_index() ( ) )
metoda indeks_radnje je radnja koja se poziva prema zadanim postavkama, nadjačat ćemo je pri implementaciji klasa potomaka.
Na prethodnoj slici, datoteka template_view.php je posebno označena - ovo je predložak koji sadrži oznake zajedničke za sve stranice. U najjednostavnijem slučaju to bi moglo izgledati ovako:
Dom
Kako bismo web stranici dali vidljiv izgled, napravit ćemo CSS predložak i integrirati ga u našu web stranicu mijenjajući strukturu HTML oznake i uključujući CSS i JavaScript datoteke:
Na kraju članka, u odjeljku “Rezultat”, nalazi se poveznica na GitHub repozitorij s projektom u koji je napravljena integracija jednostavnog predloška.
klasa Controller_Main proširuje Controller ( funkcija action_index() ( $this->view->generate("main_view.php", "template_view.php"); ) )
Metoda generirati instanci klase View prosljeđuju se nazivi datoteka općeg predloška i pogleda sa sadržajem stranice.
Osim radnje indeksa, kontroler naravno može sadržavati i druge akcije.
Ranije smo razgovarali o datoteci s općim pogledom. Razmotrite datoteku sadržaja main_view.php:
Dobrodošli!
OLOLOSHA TEAM je tim prvoklasnih stručnjaka za razvoj web stranica s dugogodišnjim iskustvom u prikupljanju meksičkih maski, brončanih i kamenih statua iz Indije i Cejlona, bareljefa i skulptura koje su izradili majstori Ekvatorijalne Afrike prije pet ili šest stoljeća. .
Ovo sadrži jednostavno označavanje bez PHP poziva.
Za prikaz glavne stranice možete koristiti jednu od sljedećih adresa:
O primjeru korištenja pogleda koji prikazuje podatke primljene iz modela bit će riječi kasnije. 2.3.2. Stvaranje stranice portfelja U našem slučaju, stranica portfelja je jedina stranica koja koristi model.
Model obično uključuje metode dohvaćanja podataka, na primjer:
Datoteka modela model_portfolio.php bit će smještena u mapu modela. Evo njegovog sadržaja:
klasa Model_Portfolio proširuje model ( javna funkcija get_data() ( return array(array("Year" => "2012", "Site" => "http://DunkelBeer.ru", "Description" => "Dark Dunkel pivo iz njemački proizvođač Löwenbraü proizveden u Rusiji od strane pivarske tvrtke "SUN InBev"."), array("Year" => "2012", "Site" => "http://ZopoMobile.ru", "Description" => "Katalog kineskih Zopo telefona na ruskom jeziku koji se temelje na Android OS-u i dodacima.", // todo); ) )
Klasa kontrolera modela nalazi se u datoteci controller_portfolio.php, ovdje je njen kod:
klasa Controller_Portfolio proširuje Controller ( funkcija __construct() ( $this->model = new Model_Portfolio(); $this->view = new View(); ) funkcija action_index() ( $data = $this->model->get_data( ); $this->view->generate("portfolio_view.php", "template_view.php", $data); ) )
u varijablu podaci zapisuje se niz koji vraća metoda dobiti_podatke, koje smo ranije razmatrali.
Ova se varijabla zatim prosljeđuje kao parametar metode. generirati, koji se također prosljeđuje: naziv datoteke sa zajedničkim predloškom i naziv datoteke koja sadrži prikaz sa sadržajem stranice.
Prikaz koji sadrži sadržaj stranice nalazi se u datoteci portfolio_view.php.
Portfelj
Godina | Projekt | Opis |
Ovdje je sve jednostavno, pogled prikazuje podatke primljene od modela. 2.3.3. Izrada ostalih stranica Ostale stranice izrađuju se na isti način. Njihov kod je dostupan u repozitoriju na GitHubu, poveznica na koju je dana na kraju članka, u odjeljku "Rezultat".3. Rezultat A evo i rezultata:
Snimka zaslona rezultirajućeg web-mjesta s posjetnicama
Link na GitHub: https://github.com/vitalyswipe/tinymvc/zipball/v0.1
Ali u ovoj verziji skicirao sam sljedeće klase (i njihove odgovarajuće tipove):
- Controller_Login u kojem se generira pregled s formom za unos logina i lozinke, nakon čega se provodi procedura autentifikacije i, ako je uspješna, korisnik se preusmjerava na admin panel.
- Contorller_Admin s radnjom indeksa koja provjerava je li korisnik prethodno bio ovlašten na web mjestu kao administrator (ako je, prikazuje se administratorski pogled) i akcijom odjave za odjavu.
Ali korištenje web okvira kao što su Yii ili Kohana, koji se sastoje od nekoliko stotina datoteka, pri razvoju jednostavnih web aplikacija (na primjer, stranica s posjetnicama) nije uvijek preporučljivo. Sada možemo stvoriti prekrasan MVC model kako ne bismo miješali Php, Html, CSS i JavaScript kod u jednoj datoteci.
Ovaj je članak više polazište za učenje CMF-a nego primjer nečeg uistinu ispravnog što možete uzeti kao temelj svoje web aplikacije. Možda vas je to čak i inspiriralo i već razmišljate o pisanju vlastitog microframeworka ili CMS-a temeljenog na MVC-u. No, prije nego što izmislite sljedeći kotač s "mjesečinom i kurvama", razmislite još jednom, možda bi bilo pametnije svoje napore usmjeriti na razvoj i pomoć zajednici postojećeg projekta?!
P.S.: Članak je prerađen uzimajući u obzir neke od komentara ostavljenih u komentarima. Kritika je bila od velike pomoći. Sudeći po odazivu: komentarima, osobnim apelima i broju korisnika koji su objavu dodali u favorite, ideja za pisanje ove objave nije se pokazala tako lošom. Nažalost, nije moguće uvažiti sve želje i napisati više i detaljnije zbog nedostatka vremena ... ali možda će to učiniti one misteriozne ličnosti koje minus originalnu verziju. Sretno s vašim projektima!
5. Izbor korisnih poveznica na temu Članak se vrlo često dotiče teme web frameworka - to je vrlo opširna tema, jer se čak i microframeworks sastoji od mnogo komponenti koje su međusobno pametno povezane i bilo bi potrebno više od jedne članak za razgovor o tim komponentama. Ipak, odlučio sam ovdje dati mali izbor linkova (na koje sam otišao dok sam pisao ovaj članak) koji se na ovaj ili onaj način odnose na temu okvira.Oznake: Dodajte oznake
U ovom ćemo članku razumjeti koncept MVC-a i kako ga, uz primjer, možete primijeniti u PHP-u.
Koncept MVC-aMVC (Model-View-Controller, " Model-Pogled-Ponašanje», « Model-View-Controller”) je obrazac dizajna aplikacije u kojem je upravljačka logika podijeljena u tri odvojene komponente na takav način da izmjena jedne od njih ima minimalan utjecaj na ostale.
MVC predložak dobro je koristiti kod izrade složenih projekata gdje je potrebno odvojiti rad php programera (ili grupu programera podijeliti u odjele), dizajnera, kodera itd.
MVC obrazac razdvaja prezentaciju, podatke i rukovanje radnjama korisnika u tri odvojene komponente:
MVC Model (Model). Model pruža podatke (obično View-u) i također odgovara na zahtjeve (obično od kontrolera) promjenom svog stanja.
MVC pogled. Odgovoran za prikaz informacija (korisničko sučelje).
MVC ponašanje (kontrolor). Tumači korisnički unos i obavještava model i pogled da reagiraju na odgovarajući način.
Radi jasnoće, shema MVC uzorka, ilustracija je navedena u nastavku.
Komponente poput prezentacije i ponašanja ovise o modelu, ali ni na koji način ne utječu na njega. Model može imati više pogleda. Možda je koncept MVC-a teško razumjeti, ali kada se jednom shvati, postaje nezamjenjiv pri razvoju aplikacija u PHP-u.
MVC u PHP-uPosebna značajka kod korištenja MVC-a u PHP-u je da postoji jedna ulazna točka u php aplikaciju, što se, na primjer, postiže na sljedeći način. Kreira se index.php kroz koji će se obrađivati svi zahtjevi, za to kreiramo .htaccess datoteku u mapi s indeksom i u nju postavimo sljedeći kod:
RewriteEngine na RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule ^(.*)$ index.php?route=$1
U navedenom kodu, prvi redak provjerava postojanje tražene datoteke, a ako ne postoji, onda se preusmjerava na index.php, inače će čak i zahtjevi za slike stranice biti preusmjereni na indeks. Posljednji redak koda pretvara zahtjeve poput index.php?route=chat/index u poput index.php/chat/index. Ako ne možete koristiti ModRewrite u svojoj aplikaciji, preusmjeravanje ćete morati izvršiti ručno.
PHP model
Podaci o PHP modelu sadržani su u njegovim atributima i mogu se mijenjati samo kroz posebne funkcije. Model može sadržavati više pogleda. U pravilu, phpmodel je klasa koja radi s bazom podataka, točnije: pisanje, čitanje, brisanje. Naravno, čitanje informacija iz baze podataka može se implementirati pomoću nekoliko pogleda (funkcija). Kao primjer, model članaka na stranici: možete dobiti određeni članak iz baze podataka, popis novijih, popularnih, neku kategoriju... sve su to prikazi modela. Radi jasnoće, u nastavku je naveden primjer php modela.
PHP kontroler (ponašanje)
PHP kontroleri primaju korisničke zahtjeve koje šaljemo preko index.php te u skladu s njima prilagođavaju rad modela. Ispravnije bi bilo reći da kontroliraju rad php aplikacije.
PHP prikaz
Pogled prati promjenu u modelu i stvara ili mijenja php sučelje aplikacije.
Popis podataka
Kako radi ovaj PHP MVC predložak?
Kada korisnik pristupi željenom url-u, odabire se odgovarajući kontroler koji se odnosi na prikaz i model te se prikazuju informacije. Drugim riječima, kontroler u mvc-u je poveznica između modela i pogleda.
Prednosti MVC uzorka pri izradi PHP aplikacije
Kao što je gore spomenuto, ovo je, prije svega, diferencijacija programera php stranice u odjele. Brzina php aplikacije također se povećava ako se izradi veliki projekt. Pa, ono što se izravno tiče samog php programera, to je ispravno strukturiranje php koda (sve je na svom mjestu, lakše je razumjeti).
MVC primjer
Nećemo se previše zadržavati na primjeru kako MVC radi, jer on već postoji. Samo ću dodati još par dijagrama za dublje razumijevanje.
Još jedna shema MVC predloška u PHP-u, više je nego razumljiva.
Uzorak Model-View-Controller (MVC) izuzetno je koristan pri izradi aplikacija sa složenim GUI-jima ili ponašanjima. Ali prikladan je i za jednostavnije slučajeve. U ovom ćemo postu izraditi igru minolovac dizajniranu prema ovom uzorku. Python je odabran kao razvojni jezik, ali to nema neki poseban značaj. Uzorci ne ovise o određenom programskom jeziku i možete jednostavno prenijeti rezultirajuću implementaciju na bilo koju drugu platformu.
Oglas Ukratko o MVC uzorkuKao što ime sugerira, MVC uzorak ima 3 komponente: model, pogled i kontroler. Svaka od komponenti obavlja svoju ulogu i zamjenjiva je. To znači da su komponente međusobno povezane samo nekim jasnim sučeljima iza kojih može stajati svaka implementacija. Ovaj pristup omogućuje zamjenu i kombiniranje različitih komponenti, pružajući potrebnu logiku rada ili izgled aplikacije. Pogledajmo funkcije koje svaka komponenta obavlja.
ModelOdgovoran za unutarnju logiku programa. Ovdje možemo sakriti načine pohranjivanja podataka, kao i pravila i algoritme za obradu informacija.
Na primjer, za jednu aplikaciju možemo izraditi nekoliko modela. Jedan će otklanjati pogreške, a drugi će raditi. Prvi može pohraniti svoje podatke u memoriju ili u datoteku, a drugi već koristi bazu podataka. Zapravo, ovo je samo obrazac strategije.
IzvođenjeOdgovoran za prikaz podataka o modelu. Na ovoj razini pružamo samo sučelje za interakciju korisnika s modelom. Smisao uvođenja ove komponente je isti kao iu slučaju pružanja različitih načina pohranjivanja podataka na temelju više Modela.
Na primjer, u ranim fazama razvoja, možemo stvoriti jednostavan prikaz konzole za našu aplikaciju, a tek onda dodati lijepo dizajniran GUI. Štoviše, ostaje moguće spremiti obje vrste sučelja.
Osim toga, treba imati na umu da je odgovornost View-a samo pravovremeni prikaz stanja Modela. Kontrolor je odgovoran za obradu radnji korisnika, o čemu ćemo sada govoriti.
KontrolorPruža vezu između modela i radnji korisnika koje proizlaze iz interakcije s prikazom. Koordinate kada se ažuriraju stanja modela i prikaza. Donosi većinu odluka o prijelazima aplikacije iz jednog stanja u drugo.
Zapravo, za svaku radnju koju korisnik može poduzeti u View-u, rukovatelj mora biti definiran u Controller-u. Ovaj rukovatelj će izvršiti odgovarajuće manipulacije na modelu i, ako je potrebno, obavijestiti View o prisutnosti promjena.
Oglas Specifikacije igre MinesweeperDosta teorije. Sada prijeđimo na praksu. Kako bismo demonstrirali MVC uzorak, napisat ćemo jednostavnu igru: Minolovac. Pravila igre su vrlo jednostavna:
Primjer onoga što dobivamo prikazan je u nastavku:
Minolovac UML dijagramiPrije nego što prijeđete na pisanje koda, bilo bi lijepo unaprijed razmisliti o arhitekturi aplikacije. Ne bi trebao ovisiti o jeziku implementacije, tako da je UML najprikladniji za naše svrhe.
Dijagram stanja ćelije igreSvaka ćelija na polju za igru može biti u jednom od 4 stanja:
Ovdje smo definirali samo stanja koja su relevantna za View. Budući da se mine ne prikazuju tijekom igre, ni odgovarajuće stanje nije predviđeno u osnovnom setu. Definirajmo moguće prijelaze iz jednog stanja ćelije u drugo pomoću UML dijagrama stanja:
Dijagram klasa minolovacaBudući da smo odlučili izgraditi svoju aplikaciju temeljenu na MVC uzorku, imat ćemo tri glavne klase: MinesweeperModel, MinesweeperView i MinesweeperController, kao i pomoćnu klasu MinesweeperCell za pohranjivanje stanja ćelije. Razmotrite njihov dijagram klasa:
Organizacija arhitekture je vrlo jednostavna. Ovdje smo jednostavno raspodijelili zadatke svakom razredu u skladu s principima MVC uzorka:
Vrijeme je da krenemo u realizaciju našeg projekta. Izabrat ćemo Python kao razvojni jezik. Zatim ćemo napisati klasu View na temelju modula tkinter.
Ali počnimo s modelom.
MinsweeperModelImplementacija modela u Pythonu izgleda ovako:
MIN_ROW_COUNT = 5 MAX_ROW_COUNT = 30 MIN_COLUMN_COUNT = 5 MAX_COLUMN_COUNT = 30 MIN_MINE_COUNT = 1 MAX_MINE_COUNT = 800 klasa MinesweeperCell: # Moguća stanja ćelije igre: # zatvoreno - zatvoreno # otvoreno - otvoreno # označeno - označeno # upitno - označeno upitnikom def __init__ ( self , red, stupac): self.row = red self.column = stupac self.state = "closed" self.mined = False self.counter = 0 markSequence = [ "closed", "flagged", "questioned" ] def nextMark (self): if self.state in self.markSequence: stateIndex = self.markSequence.index(self.state) self.state = self.markSequence[ (stateIndex + 1) % len(self.markSequence) ] def open( self ): if self.state != "flagged": self.state = "opened" class MinesweeperModel: def __init__(self): self.startGame() def startGame(self, rowCount = 15, columnCount = 15, mineCount = 15 ) : if rowCount u rasponu (MIN_ROW_COUNT, MAX_ROW_COUNT + 1): self.rowCount = rowCount if columnCount u rasponu (MIN_COLUMN_COUNT, MAX_COLUMN_COUNT + 1): self.columnCount = columnCount if mineCount< self.rowCount * self.columnCount: if mineCount in range(MIN_MINE_COUNT, MAX_MINE_COUNT + 1): self.mineCount = mineCount else: self.mineCount = self.rowCount * self.columnCount - 1 self.firstStep = True self.gameOver = False self.cellsTable = for row in range(self.rowCount): cellsRow = for column in range(self.columnCount): cellsRow.append(MinesweeperCell(row, column)) self.cellsTable.append(cellsRow) def getCell(self, row, column): if row < 0 or column < 0 or self.rowCount