Muj zasadni problem s navrhnutym resenim je ze ulpne opomnel dalsi dulezity aspekt a to je SRP. Ono verim tomu ze pro jednoduche veci to funguje hezky ale napriklad ono
$product = Product::get( $id );
co to vrati? Vrati to predpokladam Product jenze co kdyz chci jeden produkt nacitat z vice mist najednou priklad, velky globalni eshop kde v globalnim vyhledavani pouzivame Elasticsearch kuli performance ale zaroven mi nevadi ze data jsou klidne den stara. V samotnem prehledu kde ctu data ze slave repliky kde jsou povetsinou stara par vterin/minut ale pro listovani to staci. A nasledne pri zpracovani objednavky uc pracuji s mastrem kde mam zarucena aktualni data.
Tzn efektivne mam 3 repository z toho 2 jsou read-only a master umoznuje zapis. Pak musim metode get($id) rict i odkud ma nacitat jenze to musi nadrazena komponenta vedet treba ten prehled produktu v kosiku bude komponenta "prehled" pracovat s mastrem pri listovani bude pracovat se slavem takze najednou musim komponente predat informaci zda je v "master rezimu" nebo zda je ve "slave" rezimu pripadne musime udelat
Product:setPersistance("slave")
... naka logika
Product:setPersistance("master")
... jina logika
to mi jako elegantni reseni moc neprijde :/
děláte si srandu? Ukazovat neaktální data? To jako fakt? Hmm, alespoň vím, kde se tyhle zhovadilé nápady berou. K čemu je mi eshop, který mi ukazuje "skladem 100ks" ale po vložení do košíku mi to napíše "nelze dodat, není skladem". Takové řešení mi někdo ve firmě napsat, tak má na minutu padáka. Pokud neumíte udělat výkonné řešení a aktuálními daty, raději nepiště e-shopy.
Příklad z praxe :)
Eshop, 220 miliónů položek v mysql, 13 miliónů položek v prodeji. Občas zobrazíme neaktuální data a při navštívení detailu se to na pozadí aktualizuje a co nejdříve promítne do stránky. Když se to nestihne, musíme to stopnout v košíku, jinak to nejde. Nejedná se o žádný automaticky generovaný dropshipping, ale opravdu o seriózní business s kamennou prodejnou.
Můžu to mít všechno aktuální, ale ty náklady bych pak musel promítnout do ceny.
Chápu, že pro minieshop se 100, nebo 1000 položkama je to snadné, ale když bys mi s těmahle hláškama přišel do většího projektu... tak padáka... nemáš, jelikož bys ani nedostal práci.
Mate to nejako naopak
Tento kod je SRP - kazda trieda riesi prave jednu funkcionalitu. Prva riesi servirovanie dat, druha ziskanie dat z mastra, treti ziskanie dat zo slave. Kludne si mozete napisat aj stvrtu pre ziskanie dat z elasticu, bez toho aby ste musel sucastne upravovat aj rodicovsku triedu.
abstract class Product{
public function get($id){
$data=$this->getData($id);
// process and retun data
}
abstract protected function getData($id);
}
class ProductMaster(Product){
protected function getData($id){
// some logic
}
}
class ProductSlave(Product){
protected function getData($id){
// some logic
}
}
To co popisujete vy ako idealne riesenie SRP nie je, trieda riesi hned niekolko funkcnosti.
Zmysel hlavne nedava pouzivat statiku pre dynamicke data, to by bola degradacia OOP na proceduralne paradigma. Volat sa bude samozrejme $productSource->get, kde $productSource bude instncia ProductMaster alebo ProductSlave. Staticke metody funguju so statickymi polozkami definovanymi v ramci definicie triedy, k instancii objektu sa nedostanu.
Ne, v kontextu tohoto vlákna se řeší, jak udělat Product::get, když to na různým místě má načítat z různé databáze. Autor komentáře to nejspíš nazval SRP, protože chtěl říct, že načítání z DB má být v jiné třídě než Product (což je pravda).
Ten tvůj paskvil, co jsi tam napsal, tophle nejen neřeší, ale ani nedává smysl - proč bych proboha měl mít na načítání z 4 druhů DB 4 subclassy Product? A na načítání User ze 4 druhů DB budu mít další 4 subclassy od User? Možná ovládáš teoretický OOP, kde se hodně maluje a dělají se složitý stromy dědičnosti, ale pomocí toho se skutečnej udržitelnej program napsat nedá (protože jak píšeš jinde, musíš znát všechny požadavky dopředu, a to nikdy nenastane).
Nefabuluj nad tym co autor myslel, drz sa toho co napisal.
Nebudes mat 4 subclasy Product, ale 4 subclasy ProductSource. Kludne aj piatu, ak to pribudne v poziadavkach a tym ze to vlozis do subclasy, tak na povodny kod nemusis ani siahnut. Dokonca tu piatu mozes mat ako zvlast balik, a v priebehu CI si ju natiahnes cez composer len ak to cielove prostredie bude potrebovat.
Co sa tyka mojich znalosti OOP, tak tie som uz realne pouzil a nie len v ramci PHP, ale aj v ramci komplexnejsich jazykov. SOLID je podla teba len take malovanie alebo by sa malo pouzivat aj v PHP?
Prave ze preto ze VZDY ratam s tym ze poziadavky nebudu konecne, tak nespacham aplikaciu tym stylom ze budem mat funkcionalitu natvrdo v kode. Nikdy nefabulujem nad tym ze toto alebo toto by malo byt definitivne. Tak ako si to popisal ty, pretoze pri rozsireni nechcem prepisovat projekt na niekolkych miestach.
Co je ten ProductSource, o kterým pořád mluvíš? V tvojí odpovědi je abstract Product, ProductMaster a ProductSlave. Což je blbost a jen se ti nechce to přiznat, tak jsi začal mlít o nějakým ProductSource (aby bylo jasno, Product je Active Record třída, která představuje řádek v databázi - to se nesnaž zase zpochybňovat, tak to je).
Stebou diskusia nemamoc zmysel, posuvas branky tym ze sa snazis zmenit kontext. Povodny kontext je SRP a moj prispevok sa tykal dedicnosti versus multifunkcionality volenej parametrom.
Si predstav ze Product nemusi byt nutne riadok v DB (strasny demencia snazit sa chapat relacne data ako objektove data). Kludne to bude zaznam v SAPe, pristupny cez SOAP, i ked pravda s tym sa ty asi ani nestretnes.
Ty si fakt nevidíš do huby :-)
RS v původním komentáři psal o tom, že statická Product::get
se blbě konfiguruje, odkud má brát data. Ty jsi přišel s tím, že se udělá ProductMaster
a ProductSlave
. Pokud teda, jak teď tvrdíš, tvůj kód nebyl reakce na něj, ale "sa tykal dedicnosti versus multifunkcionality volenej parametrom", proč jsi ho tam psal? Když mně radíš "Nefabuluj nad tym co autor myslel, drz sa toho co napisal"?
A teď začínáš s tím, že "Product nemusi byt nutne riadok v DB". V diskuzi pod článkem o Jetu, kde Product je řádek v DB. A ostatní obviňuješ z posouvání branek :-D
Ty tvoje výplody mi dost připomínají horečnatý vize chlápka jménem Jegor Bugajenko (Yegor Bugayenko) , pro kterýho OOP je náboženství a vede k naprosto nesmyslnýmu a strašnýmu kódu.
Na statickej Product::get
je blbe hlavne to ze neizoluje jednotlive instancie triedy. Ja som ju previedol na dynamicku formu. Potom tam bol tam navrh na static metodu, ktorej jednotlive spagety sa volia parametrom. Ktore z toho podla teba splna Single responsibility principle?
Nemiesaj sem stale DI, reprezentaciu pruduktu v db, ani definiciu toho co vlastne produkt je. V kontexte vlakna tykajuceho sa SRP je to irelevantne.
(Bohužel nejde udělat edit příspěvku): Přečetl jsem si tvoji úvodní reakci ještě několikrát, abych se pokusil zjistit, jestli jsi to nemyslel celý třeba nějak jinak a nejde jenom o nedorozumění. Ale teď mi přijde, že tam tvrdíš, že když abstract class Product
řeší jednu věc a class ProductMaster extends Product
úplně jinou věc, tak je to SRP. Pokud to tak je, tak je to docela zásadní nepochopení základních principů příčetnýho kódování. Proč by proboha v takovým případě ProductMaster vůbec měl dědit od Product?
A navíc jsi vůbec nepohopil ten komentář, na kterej jsi reagoval. Tam nikdo nepopisuje nic jako "idealne riesenie", tam naopak namítá, že v Jetu to nejde udělat správně bez porušení SRP.
Tady bude asi problem v namingu (aneb jeden z nejvetsich programatorskych problemu :) )
Pokud je opravdu Product jen Storem tak by se tak mel i jmenovat jinak neni jasne co je vlastne zodpovednosti objektu Produkt ? je to reprezentace Produktu? Je to reprezentace Storage ?
Priznam se ze to vase reseni me trosku desi protoze
class ProductMaster(Product) imlikuje ze ProductMaster <b>JE</b> Product ale pokud Product je DTO a ProductMaster je repository tak je ta dedicnost postavena spatne..predpokladam tedy ze zakladni problem v porozumneni je v tom co je vlastne resposibilita classy Product. a co vraci.. pokud Product vraci instanci napriklad ProductDTO/ProductActiveRecord tak pak asi ok (i kdyz active record nemam rad z duvodu zde jich popsanych). V opacnem pripade se jedna o poruseni SRP kdy micham zodpovednosti za nacitani a reprezentaci
$product = Product::get( $id );
a
$product = $product->get( $id );
se liší jen ve filozofii.
V prvém případě mám defakto globální objekt. Veškerá logika rozhodování odkud nebo dokonce co získám je definována vevnitř. Abych tuto logiku mohl nějak ovlivnit musím najít správné místo a šáhnout dovnitř. Nemohu mít dvě instance jen různě nakonfigurované (třeba porovnávat ze dvou různých zdrojů.)
V druhém případě mám instanci. Ta někde vzniká. Což má za důsledek že nejenom že to jde snadno najít, ale taky ten vznik mohu snadno nahradit za své řešení - je to jen proměnná.
Toto:
Product:setPersistance("slave")
... naka logika
Product:setPersistance("master")
... jina logika
je v celku provařená věc. V průběhu času se vám mění chování toho objektu. Velice nepříjemné. Nemám to rád.
Přečteno 20 188×
Přečteno 18 061×
Přečteno 17 489×
Přečteno 17 029×
Přečteno 15 691×