I tex en webbutik finns det två viktiga objekt och det är kundvagnen och ordern. Kundvagnen har en del likheter med en order. Som tex produkter, totalt pris m.m. Skulle ni skapat en basklass för att hantera dessa likheter och som order och kundvagn ärver ifrån eller hur skulle ni gjort? Vanligtvis inte och anledningen till det är att eftersom order och kundvagn är olika koncept i systemet så måste man synkronisera förändringarna i basklassen och vara säker på att inte konceptuella förändringar i order (som påverkar basklassen) inte påverkar också kundvagnen. Jag misstänkte detta och när jag började fundera över hur repositoryn skulle se ut så förstod jag att detta inte riktigt var en bra väg att gå. Även om objekten har vissa snarlika delar så är det två olika koncept och att hantera två olika koncept i en repository skulle inte bli användarvänligt ur utvecklarsynpunkt. Shared kernel kommer från Eric Evans och Domain Driven Design. Finns lite mer information http://softwareengineering.vazexqi.com/articles/2006/10/15/ddd-maintaining-model-integrity Men du kan ju ha 2 olika Repository. Säg att du har basklassen "cart" (redan här blir det problem med namnet :) ). Sedan 2 klasser: Order och ShoppingCart som ärver från cart. Du kan då skapa 2 olika repository 1 för Order och 1 för ShoppingCart. Det är sant att jag skulle kunna haft en basklass för en repository! Tänkte inte på det... Bra att du påpeka det! +1 till Patrik. En sak som kan vara svår men som jag tycker kräver en extra tankegång är just klasser som ser lika dana ut. I vår vackra värld skiljer sig kanske inte en spann så mkt från en kanna vatten. Båda kan vara runda och ha olika mkt vatten i sig. Men bara för det kan inte en spann ärva ett glas bara för att de är lika. De är trotts allt två olika saker. Men glas och kanna bör kunna ärva av en klass typ behållare ;). Base prefixet tycker jag ofta klingar fel, jag tycker man isåfall borde kunna döpa klassen till något mer beskrivande.OrderBase för Order och ShoppingCart?
Sv: OrderBase för Order och ShoppingCart?
Reuse är ofta något man eftersträvar, men bara reuse om koncepten är samma, annars blir det för lätt att låta koncepten påverka varandra.
/om/ det är så att man vet att de grundläggande koncepten är samma så kan man skapa en s k "shared kernel", men det förutsätter tydliga enhetestester på den modulen för att testa att både kundvagn och orders koncept alltid fungerar som de skall. Så att man kan vara säker på att en förändring för ett koncept inte förstör ngt för det andra konceptet.
Du måste också fundera på "Liskov substition principle" i sammanhang med arv, det betyder att man skall kunna förvänta sig att alla operationer på ett objekt som refereras med bastypen beter sig på liknande sätt. Läs mer Liskov här: http://www.lostechies.com/blogs/chad_myers/archive/2008/03/11/ptom-the-liskov-substitution-principle.aspx Sv:OrderBase för Order och ShoppingCart?
Det med "shared kernel" har jag aldrig hört talas om. Hur implementeras det?Sv: OrderBase för Order och ShoppingCart?
Sv: OrderBase för Order och ShoppingCart?
Sedan lägger du allt som hanteras likadant i din "cart" och det som hanteras olika läggs i respektive klass. Problemet är att du efterhand kommer att märka att saker som du trodde skulle hanteras likadant inte kommer att gör det. Ett tydlig exempel på det är priset.
I din ShoppingCart så vill du att priset på en artikel skall hämtas från artiklen (eftersom priset på varan kan ha ändrats från det man la ner den i shoppingcarten tills dess att man skall betala) men priset på en vara i din order skall inte vara kopplat till artiklenspris mer än precis när man köper vara så där så måste man spara ner priset separat och inte ta artiklenspris när ordern senare skall visas...
- MSv:OrderBase för Order och ShoppingCart?
Exemplet som du tar upp med prisändringar är också ett väldigt bra exempel på hur det skulle kunna gå fel.
Jag tycker också att CartBase eller OrderBase inte är några bra namn på en basklass om man skulle låta Order och ShoppingCart ärva från den. Heter den CartBase eller ShoppingCartBase så tycker jag namnet blir hårt kopplat till ShoppingCart och inte till Order. Heter basklassen OrderBase då blir det tvärtom, dvs Order blir hårdare kopplat till basklassen. Det är dock mer på en intuitivnivå men kanske skulle just denna intuitiva känsla kunna vara en indikation på att en basklass inte är bra i detta läget. Dvs hittar man inte ett bra namn på sin basklass som fångar subklasserna då kan det vara en indikation på att någon av subklasserna är en främmande potatis i potatiskorgen... :)Sv: OrderBase för Order och ShoppingCart?
Order IS A Cart?
Det finns stor risk att Orders relation till Cart kan bryta LSP.
Låt oss säga att vi låter Order ärva från Cart. Sedan skapar någon metoden M som tar en Cart. Denna person utgår från att Cart är en Cart och inte en Order.. Så tar någon annan och skickar in en Order till metoden M, vilket går eftersom den ärver från Cart... då kan det bli riktigt fel om vi bryter mot LSP.
Om nu Order ärver från Cart och vi ser på Order så tycker vi att den ser rätt ut.. Sedan tar vi en titt på ShopingCart och den ser också rätt ut.. Men som Uncle Bob säger: "A model viewed in isolation, cannot be meaningfully validated".Sv:OrderBase för Order och ShoppingCart?
Det är väldigt ofta jag i alla fall sett utvecklare använda arv till saker som bara hjälper dem att slippa skriva en ny klass med nästan samma signatur men då missbruka arvet och OOs mening. Sv: OrderBase för Order och ShoppingCart?
Sv: OrderBase för Order och ShoppingCart?
Men i detta fallet, kan man inte se Kundvagnen som en Order fast har tillståndet ej godkänd av kund eller liknande?
Så när kunden är klar med ordern och skickat in den så ändras tillståndet.