Table of Contents • • • • • General Layered Architecture Sample Application Domain-Driven Design (DDD) Building Blocks Spring Layered Architecture Inversion of Control General Layered Architecture • Layer – a discrete, orthogonal area of concern within an application • Top layer (front end, presentation) – UI – end user interaction – Web – navigation logic • Middle layer – Service – coarse-grained system functionality (use cases), transaction (unit of work) , stateless – Domain – entities, value objects, business logic – the true implementation of the use cases • Bottom layer (back end, infrastructure) – Persistence – store & retrieve instances of the object model – Integration – communication between systems Sample Application – Pet Store (see jpetstore example) • Use Cases – Fill shopping cart – Sign in – Register customer – Register order (checkout); – Process order • Business Rules – Large orders must be approved DDD Building Blocks • Entity, Value Object, Aggregate • Repository, Service • Refine Associations, Validation Entity • An object defined primarily by its identity is called an ENTITY. • When an object is distinguished by its identity, rather than its attributes, – Keep the class definition simple and focused on life cycle continuity (status) and identity (id). – Be alert to requirements that call for matching objects by attributes (finders). – The model must define what it means to be the same thing (equality). Value Object • An object that represents a descriptive aspect of the domain with no conceptual identity is called a VALUE OBJECT. • When you care only about the attributes of an element of the model, classify it as a VALUE OBJECT. – Treat the VALUE OBJECT as immutable. (it cannot be changed except by full replacement) – Don't give it any identity and avoid the design complexities necessary to maintain ENTITIES. Store - Entities and Value Objects Aggregate Context/Problem • Consistency of changes in a model with complex associations • Invariants that apply to closely related groups of objects, not just discrete objects • Locking schemes cause multiple users to interfere with each other and make a system unusable. Solution • Cluster the ENTITIES and VALUE OBJECTS into AGGREGATES and define boundaries around each. • Choose one ENTITY to be the root of each AGGREGATE, and control all access to the objects inside the boundary through the root. • Allow external objects to hold references to the root only. • Transient references to internal members can be passed out for use within a single operation only. Store - Aggregates Store - Validation • Define object validation as part of the domain • Use the Strategy design pattern to be able to change the validation algorithms without changing the model • Validation algorithms are defined for each aggregate root Repository • A REPOSITORY represents all objects of a certain type as a conceptual set (usually emulated). • For each type of object that needs global access, create a repository – Provide methods to add and remove objects, which will encapsulate the actual insertion or removal of data in the data store. – Provide methods that select objects based on some criteria and return fully instantiated objects or collections of objects whose attribute values meet the criteria, thereby encapsulating the actual storage and query technology. • Provide REPOSITORIES only for AGGREGATE roots that actually need direct access. Store - Repositories Service • A SERVICE is an operation offered as an interface that stands alone in the model, without encapsulating state, as ENTITIES and VALUE OBJECTS do. • SERVICES are a common pattern in technical frameworks, but they can also apply in the domain layer. • A good SERVICE has three characteristics. – The operation relates to a domain concept that is not a natural part of an ENTITY or VALUE OBJECT. – The interface is defined in terms of other elements of the domain model. – The operation is stateless. • When a significant process or transformation in the domain is not a natural responsibility of an ENTITY or VALUE OBJECT, add an operation to the model as a standalone interface declared as a SERVICE. Store – Product Catalog Service Presentation Layer: • Get categories • Get products by category • Get items by product • Other CRUD operations, e.g. remove category which also includes removing products and items • etc Store – Ordering Service Presentation Layer: • Get user by username • Create order • Approve order • Reject order • Process order • Get open orders • Get orders by customer • Get orders for approval • Enforce business rules DDD Layered Architecture Inversion of Control (IoC) Suppose we have a component that uses another component that implements a given interface. How the component could obtain a plugin implementation? Dependency Lookup. Use Abstraction a factory bean to lookup Dependent for the collaborator, such as: object I i = factoryBean.getBean(“i”); i.f(); ... This code is usually put in C. This design follows the dependency inversion principle. Collaborator object IoC (cont.) Dependency Injection. Use an assembler object that injects (populates) a field in the dependent object. Based on a config, finds an appropriate implementation, creates a collaborator, and injects that object in the dependent object. IoC (cont.) Constructor Injection. The Assembler uses the constructor to inject or set the implementation. Assembler proceeds as follows: I i = new IImpl(); C c = new C(i); IoC (cont.) Setter Injection. The Assembler uses a setter method to inject or set the implementation. Assembler proceeds as follows: I i = new IImpl(); C c = new C(); c.setI(i) IoC (cont.) • <?xml version="1.0" encoding="UTF-8"?> • • <beans xmlns=“..."> <bean id=“cBean" class=“C"> <property name=“i" ref=“iBean" /> </bean> <bean id=“iBean" class=“IImpl"> </bean> </beans> • public class C { private I i; public void setI(I i) { this.i = i; } public void fun() {i.f();} } FileSystemXmlApplicationContext factory = new FileSystemXmlApplicationContext("classpath:conf/spring-config.xml"); C c = (C) factory.getBean(“cBean"); c.fun();