520 likes | 605 Views
Intentions & Interfaces Making Patterns Concrete. Udi Dahan – The Software Simplist Enterprise Development Expert & SOA Specialist. Session Code: <Session code>. Books, and books, and books, and books…. Flexibility brings many benefits. Agenda. Intentional Interfaces. Data Access.
E N D
Intentions & InterfacesMaking Patterns Concrete Udi Dahan – The Software Simplist Enterprise Development Expert & SOA Specialist Session Code: <Session code>
Agenda Intentional Interfaces Data Access Service Layer Validation
Existing solutions Strategy Pattern Visitor Pattern
Visitor pattern Requires a method for each ConcreteElement
Strategy pattern Requires all classes to contain a strategy
Danger Application Code May cause a collapse of application structure Infrastructure Code at Co ion de lic App Infrastructure Code
Doing too muchcan hurt Y ou A ren‘t G onna N eed I t
What needs to flex? “Prediction is very difficult, • especially if it's about the future.” -- Niels Bohr Physics Nobel prize 1922
Flexibility you seek? Hmm? Made your roles explicit, have you? No? That is why you fail.
Make Roles Explicit
Some well known interfaces ISerializable IFather IHusband Serializable IGoToWork IComeHome IWashTheDishes
Intentional Interfaces Data Access Service Layer Validation
The old “object-oriented” way • boolIsValidating; .Validate(); Customer .Validate(); Address * .Validate(); Order But what if we start here? Persistence .Persist(c);
Roles as Marker Interfaces IEntity Customer Order IValidator<T> ValidationError Validate(T entity); where T : IEntity
Validation Implementation IValidator<T> Customer CustomerValidator: IValidator<Customer> ValidationError Validate(T entity); ValidationError Validate(Customer entity);
Extensible validation when persisting .Persist(Customer) Persistence Service Locator Get<IValidator<Customer>> new Validate(Customer) Customer Validator
Extensible and Object Oriented Customer Validator .Validate(); Customer
Application code stays simple Application Code .Persist(Customer) Infrastructure Code
Intentional Interfaces Data Access Service Layer Validation
Regular Service Layer Code publicvoidMake_Customer_Preferred(Guid id) { using (ISession s = ORM.Open_Session()) using (ITransactiontx = s.Begin_Transaction()) { Customer c = s.Get<Customer>(id); c.Make_Preferred(); tx.Commit(); } }
Loading graphs of objects public class Customer { publicvoidMake_Preferred() { foreach(Order o inthis.UnshippedOrders) foreach(Orderlineolino.OrderLines) ol.Discount(10.Percent); } } Lazy Loading
Dangers of Lazy Loading public class Customer { publicvoidMake_Preferred() { foreach(Order o inthis.UnshippedOrders) foreach(Orderlineolino.OrderLines) ol.Discount(10.Percent); } } DB
Loading graphs of objects Making a customer “preferred” Adding an Order Customer Customer Order OrderLine
Different “Fetching Strategies” for the same customer
Make Roles Explicit
Use interfaces to differentiate roles IMakeCustomerPreferred IAddOrdersToCustomer void MakePreferred(); void AddOrder(Order o); Customer
Service Layer Specifies Role publicvoidMake_Customer_Preferred(Guid id) { using (ISession s = ORM.Open_Session()) using (ITransactiontx = s.Begin_Transaction()) { IMakeCustomerPreferred c = s.Get<IMakeCustomerPreferred>(id); c.Make_Preferred(); tx.Commit(); } }
Infrastructure Roles The Fetching Strategy
Extend behavior around role IMakeCustomerPreferred IAddOrdersToCustomer void MakePreferred(); void AddOrder(Order o); Customer T MakeCustomerPreferredFetchingStrategy : IFetchingStrategy<IMakeCustomerPreferred> Inherits string Strategy { get { return “UnshippedOrders, OrderLines”; } } IFetchingStrategy<T>
The Extensible Way .Get<IMakeCustomerPreferred>(id) Persistence Load graph Service Locator Get<IFetchingStrategy<IMakeCustomerPreferred>> DB new Get strategy Make_Customer_Preferred_Fetching_Strategy
Intentional Interfaces Data Access Service Layer Validation
Regular Service Layer Code Customer Service void Change_Address(Guid id, Address a); void Make_Preferred(Guid id); voidChange_Credit(Credit c);
Applying the pattern again… IMessage IMessageHandler<T> void Handle(T message); where T : IMessage
The messages: Change_Address_Msg Make_Preferred_Msg Change_Credit_Msg IMessage
The message handlers: H1: H2: H3: IMessageHandler<T> void Handle(T message); IMessageHandler<Change_Address_Msg> IMessageHandler<Make_Preferred_Msg> IMessageHandler<Change_Credit_Msg>
There can be more than one… H1: H4: Change_Address_Msg IMessageHandler<Change_Address_Msg> IMessageHandler<Change_Address_Msg>
Putting it all together… .Handle(m); Service Locator .Handle(m); GetAll<IMessageHandler<Change_Address_Msg>> new H1 H4
Intentional Interfaces Data Access Service Layer Validation