Onion Information
Objektno modeliranje i programiranje web aplikacija. Objektno-relacijsko preslikavanje - GASERI
Razvoj web aplikacija i usluga
Onion Details
Page Clicks: 0
First Seen: 03/15/2024
Last Indexed: 10/23/2024
Onion Content
Preskoči na sadržaj Objektno orijentirano modeliranje i programiranje web aplikacija. Objektno-relacijsko preslikavanje doc. dr. sc. Vedran Miletić, vmiletic@inf.uniri.hr , vedran.miletic.net Fakultet informatike i digitalnih tehnologija Sveučilišta u Rijeci, akademska 2021./2022. godina Objektno orijentirano modeliranje i programiranje Za modeliranje koristit ćemo po potrebi Allen Holub's UML Quick Reference : Use-Case (Story) Diagram Static-Model (Class) Diagram Interaction (Dynamic-Model) Diagrams Objektno orijentirano programiranje (prema Wikipediji ): programska paradigma temeljena na objektima koji sadrže podatke (polja, atribute ili svojstva) i kod (procedure ili metode) četiri temelja: enkapsulacija, apstrakcija, nasljeđivanje i polimorfizam Enkapsulacija (1/2) 🙋 Pitanje: Je li ovo primjer enkapsulacije? class Account balance ; } public function alterBalance ( int $amount ) : void { $this -> iban += $amount ; } Apstrakcija $host , 'port' => $port , 'auth' => true , 'username' => $username , 'password' => $password ]); $mail = $smtp -> send ( $to , $headers , $email_body ); // ... } Ponovno iskoristive komponente Izvor: Reusable Components (MonkeyUser, 7th September 2021) Nasljeđivanje class PrintJob { constructor ( printer , numberOfPages ) { this . printer = printer ; this . numberOfPages = numberOfPages ; } class PaidPrintJob extends PrintJob { constructor ( printer , paymentAccount ) { this . paymentAccount = paymentAccount ; super ( printer ); } chargeAccount () { let pricePerPage = this . printer -> getPricePerPage (); this . paymentAccount -> pay ( this . numberOfPages * pricePerPage ); } Polimorfizam from django.db import models class Question ( models . Model ): question_text = models . CharField ( max_length = 200 ) pub_date = models . DateTimeField ( 'date published' ) class Article ( models . Model ): article_text = models . TextField () pub_date = models . DateTimeField ( 'date published' ) q = Question ( question_text = "What's new?" , pub_date = timezone . now ()) a = Article ( article_text = "Lorem ipsum dolor sit amet, consectetur..." , pub_date = timezone . now ()) objs = [ q , a ] for obj in objs : print ( obj . pub_date ) Rubni slučajevi Izvor: Web App - Edge Cases (MonkeyUser, 15th October 2019) SOLID (1/2) Prema Wikipediji , SOLID je skup načela koji je 2000. godine predložio američki softverski inženjer Robert C. Martin (kolokvijalno Uncle Bob ) u svome radu Design Principles and Design Patterns : What goes wrong with software? The design of many software applications begins as a vital image in the minds of its designers. At this stage it is clean, elegant, and compelling. (...) But then something begins to happen. The software starts to rot. At first it isn't so bad. An ugly wart here, a clumsy hack there, but the beauty of the design still shows through. Yet, over time as the rotting continues, the ugly festering sores and boils accumulate until they dominate the design of the application. The program becomes a festering mass of code that the developers find increasingly hard to maintain. (...) SOLID (2/2) Michael Feathers je uveo mnemoničku kraticu za pet načela dizajna čiji je cilj softver učiniti razumljivijim, fleksibilnijim i lakšim za održavanje: ( S ) Načelo pojedinačne odgovornosti (engl. single-responsibility principle ) ( O ) Načelo otvoreno-zatvoreno (engl. open-closed principle ) ( L ) Liskovino načelo zamjene (engl. Liskov substitution principle ) ( I ) Načelo razdvajanja sučelja (engl. interface segregation principle ) ( D ) Načelo inverzije zavisnosti (engl. dependency inversion principle ) Načelo pojedinačne odgovornosti (1/4) ( S ) Načelo pojedinačne odgovornosti (engl. single-responsibility principle ): klasa bi trebala imati samo jednu odgovornost, odnosno samo promjene na jednom dijelu specifikacije softvera trebale bi utjecati na specifikaciju klase (prema Wikipediji ). Načelo pojedinačne odgovornosti (2/4) 🙋 Pitanje: Zadovoljava li ova klasa načelo pojedinačne odgovornosti? $this -> author -> getName (), "surname" => $this -> author -> getName ()]); } public function getTitle () { return $this -> title ; } Načelo pojedinačne odgovornosti (3/4) 🙋 Pitanje: Zadovoljava li ova klasa načelo pojedinačne odgovornosti? author ; } public function getTitle () { return $this -> title ; } Kako ćemo dobiti podatke o autoru u formatu JSON? Načelo pojedinačne odgovornosti (4/4) Jedno moguće rješenje: $this -> name , "surname" => $this -> surname ]) } Načelo otvoreno-zatvoreno (1/4) ( O ) Načelo otvoreno-zatvoreno (engl. open-closed principle ): dijelovi softvera trebali bi biti otvoreni za proširenje, ali zatvoreni za izmjene (prema Wikipediji ). Načelo otvoreno-zatvoreno (2/4) 🙋 Pitanje: Zadovoljava li ova klasa načelo otvoreno-zatvoreno? loginStudent ( $user ); } else if ( $user instanceof Professor ) { $this -> loginProfessor ( $user ); } // ... } Načelo otvoreno-zatvoreno (3/4) 🙋 Pitanje: Zadovoljava li ova klasa načelo otvoreno-zatvoreno? autheticate (); } // ... } Načelo otvoreno-zatvoreno (4/4) where ( 'user_id' , $this -> user -> id ) -> get (); } Liskovino načelo zamjene (3/3) dbConnection = $dbConnection ; } // ... } Načelo inverzije zavisnosti (3/3) dbConnection = $dbConnection ; } // ... } Primjena SOLID načela u suvremenim aplikacijama Katerina Trajchevska iz Adeve u objavi na blogu pod naslovom SOLID Design Principles: The Guide to Becoming Better Developers piše: Product owners don't always understand the implications of bad software design principles. It's on us, as engineers, to consider the best design practices when estimating and make sure we write code that's easy to maintain and extend. SOLID design principles can help us achieve that. Snimka predavanja na temu: Becoming a better developer by using the SOLID design principles by Katerina Trajchevska ( Laracon EU , 28th January 2019) Relacijski model Recimo da je neka teretana predstavljena relacijskim modelom (stil označavanja: primarni ključ , vanjski ključ ): Član ( ID člana , Ime, Adresa, Grad, Poštanski broj, Županija, Telefonski broj, E-mail) (npr. Hrvoje, Dora) Članarina ( Kod članarine , Opis članarine) (npr. mjesečna, godišnja) Uplata članarina ( Broj uplate članarine , ID člana , Datum) (npr. 1 godišnja + 2 mjesečne na 14. listopada 2021.) Stavka uplate članarine ( Broj uplate članarine , Broj stavke uplate članarine , Kod članarine , Količina) (npr. godišnja članarina na specifičnoj uplati) Za vizualizaciju možete iskoristiti npr. PonyORM Entity Relationship Diagram Creator koji može i generirati kod za PonyORM (u Pythonu, donekle sličan Djangu). Pretvorba relacijskog modela u Django modele from django.db import models class Member ( models . Model ): name = models . CharField ( max_length = 50 ) address = models . CharField ( max_length = 50 ) city = models . CharField ( max_length = 30 ) postal_code = models . IntegerField () county = models . CharField ( max_length = 30 ) phone_number = models . CharField ( max_length = 20 ) # class Membership class MembershipPayment ( models . Model ): member = models . ForeignKey ( Member , on_delete = models . CASCADE ) date = models . DateField () # class MembershipPaymentItem Pretvorba Django modela u SQL (1/2) Django će na temelju definiranih modela generirati SQL. Oblik (tzv. dijalekt) SQL-a ovisit će o korištenom sustavu za upravljanju bazom podataka, a podržani sustavi su: MariaDB/MySQL (prvi primjer u nastavku) PostgreSQL (ostali primjeri u nastavku) SQLite Oracle Pretvorba Django modela u SQL (2/2) CREATE TABLE members ( id INT PRIMARY KEY , name VARCHAR ( 50 ), address VARCHAR ( 50 ), city VARCHAR ( 30 ), postal_code INT , county VARCHAR ( 30 ), phone_number VARCHAR ( 20 ) ); CREATE TABLE membership_payment ( id INT PRIMARY KEY , member_id INT UNSIGNED NOT NULL , date DATE , CONSTRAINT ` fk_membership_payment_member ` FOREIGN KEY ( member_id ) REFERENCES member ( id ) ON DELETE CASCADE ON UPDATE RESTRICT ); Upiti u Djangu i relacijskoj bazi (1/2) Koristimo ranije prikazane klase i podatke spremamo korištenjem sustava za upravljanje bazom podataka PostgreSQL . Na temelju koda: members = Member . objects . all () Django generira upit: SELECT * FROM members ; Na temelju koda: ivan_horvat = Member . objects . get ( name = "Ivan Horvat" ) Django generira upit: SELECT * FROM members WHERE name = "Ivan Horvat" ; Upiti u Djangu i relacijskoj bazi (2/2) Na temelju koda: ivans = Member . objects . filter ( name__contains = "Ivan" ) Django generira upit: SELECT * FROM members WHERE name LIKE "%Ivan%" ; Na temelju koda: payments_ivan_horvat = MembershipPayment . objects . get ( member = ivan_horvat ) Django generira upit: SELECT * FROM membership_payments WHERE member_id IN ( SELECT id FROM members WHERE name = "Ivan Horvat" ); Objektno-relacijsko preslikavanje Prema Wikipediji : programska tehnika za pretvorbu između nekompatibilnih sustava tipova korištenjem objektno orijentiranih programskih jezika unos u tablici u relacijskoj bazi podataka postaje objekt u programu i obrnuto npr. Hibernate (Java), PonyORM (Python), Sequelize (JavaScript) i Doctrine (PHP) čitavi okviri uglavnom integriraju ORM, primjerice: Django Model Laravel Eloquent Ruby on Rails ActiveRecord generira upite za dohvaćanje podataka i migracije (promjene sheme) Migracije u Djangu $ ./manage.py makemigrations Migrations for 'members' : members/migrations/0002_auto.py: Add field e-mail on member from django.db import migrations , models class Migration ( migrations . Migration ): dependencies = [( 'migrations' , '0001_initial' )] operations = [ migrations . AddField ( 'Member' , 'e-mail' , models . CharField ( max_length = 30 )), ] Na temelju ove migracije Django generira upit: ALTER TABLE members ADD COLUMN e_mail VARCHAR ( 30 ); Migracije u web aplikacijama otvorenog koda Phabricator : migracije se nalaze u repozitoriju izvornog koda, u direktoriju resources/sql u poddirektorijima patches i autopatches ; napisan u obliku SQL upita za MariaDB/MySQL (drugi sustavi nisu podržani) Flarum : migracije se nalaze u repozitoriju izvornog koda, u direktoriju migrations ; koristi Laravel Eloquent Canvas LMS : migracije se nalaze u repozitoriju izvornog koda, u direktoriju db/migrate ; koristi Ruby on Rails ActiveRecord Nerelacijske baze podataka Prema Wikipediji , dio Yenove taksonomije NoSQL baza podataka: međuspremnik ključeva i vrijednosti (engl. key-value cache ) npr. Memcached , Redis često se koriste kao međuspremnik podataka dohvaćenih iz relacijskih baza, npr. Memcached u Djangu , Memcached ili Redis u Ruby on Railsu pohrana ključeva i vrijednosti (engl. key-value store ) npr. ArangoDB , Couchbase , Redis pohrana dokumenata, npr. ArangoDB , Couchbase , Firebase , MongoDB pohrana grafova, npr. ArangoDB , Neo4j , OrientDB Author: Vedran Miletić