[Study Note] Patterns in Practice 20100406
[Persistence Patterns]
Domain Models
a domain model is an object model of the domain that incorporates both behavior and data.
the role of database and data access code in system:
- The database is the keystone of the application and a business asset. The data access code and even the application or service code are simpley mechanisms to connect the database with the outside world.
- The business objects in the middle tier and the user interface or service layer are the application, and the database is a means to reliably persist the state of the business object between sessions.
Mapping Objects to Database
Active Record
Active Record pattern: An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logci on the data.
An Active Record approach puts persistence methods directly onto the entity object.
Active Record approach is very easy to keep the database and object model synchronized.
Lean Programming
Lean Programming eliminate wasted effort in development projects by favoring “pull” design over “push” design. The infrastructure concerns like persistence should only be designed and built to satisfy the needs of business requirements ( pulled on demond ) instead of building the data access layer code that you think the application will need later ( pushed ).
develop the system incrementally by developing vertically – by building one feather at a time instead of building the systme one horizontal layer at a time.
Data Mapper
Data Mapper pattern: a layer of mapper objects that move data between objects and a database while keeping them independent of each other and the mapper classes themselves.
Active Record is best for systems with simpler domain logic, CRUD-intensive applications and situations where the domain model doesn’t need to diverge much from the database structure.
Data Mapper is more appropriate for systems with complex domain logic where the shape of the domain model will diverge considerably from the database model. Data Mapper also decouples your domain model classes from the persistence store. Data Mapper approach is more applicable to the Test Driven Development, Domain Driven Design architectural approach
Using a Repository
Repository pattern : mediates between the domain and data mapping layers using a collection – like interface for accessing domain objects.
the Repository pattern just means putting a facade over your persistence system so that you can shield the rest of your application code from having to know how persistence works.
Identity Map
an Identity Map pattern ensures that each object gets loaded only once by keeping every loaded object in a map and looks up objects using the map when referring to them.
use the lifecycle management feature of an Inversion of Control tool (StructureMap, Windsor, Ninject, and other) to ensure that all classes in a single HTTP request or thread are using the same underlying Identity Map.
The Unit of Work pattern is another way to manage a single Identity Map across multiple classes in the same logical transaction.
Lazy And Eager Loading
in the Lazy Loading pattern, you defer initializing the object until just before it’s need.
NHibernate implements lazy loaded properties by creating a dynamic subclass of Customer that overrides the HomeAddress property to make it lazy loaded. The HomeAddress property needs to be marked as virtual in order to allow a subclass to override the property.
这一段话解释清楚了为什么使用 NHibernate 的时候,Entity 里面的 property 需要 virtual。但是为什么所有的 property 都需要 virtual ? 难道所有的 property 都默认为 lazy loading.
the only way to reliably tune an application for performance is to use an empirical measurement of performance with a profiler.
Virtual Proxy Pattern
Lazy loading is often implemented by using a virtual proxy object that looks just like the real object to be loaded later.
Taking the Next Step
Patterns of Enterprise Application Architecture, Martin Fowler
- Unit of Work
- Specifications
- Persistence Ignorance
.NET ecosystem
- Entity Framework and LINQ to SQL
- NHibernate – Data Mapper
- SubSonic – popular Active Record implementation for .NET programming
- iBatis.Net – full control over authoring the SQL statements
- LLBLGen Pro – unique querying abilities.
[The Unit Of Work Pattern And Persistence Ignorance]
The Unit of Work Pattern
The Unit of Work pattern maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems. – Martin Fowler
Examples of a Unit of Work
- ITransaction interface in NHibernate
- DataContext class in LINQ to SQL
- ObjectContext class in the Entity Framework
- venerable DataSet
responsibilities of the Unit of Work
- Manage transaction
- Order the database inserts, deletes, and updates.
- Prevent duplicate updates.
Using the Unit of Work
One of the best ways to use the Unit of Work pattern is to allow disparate classes and services to take part in a single logical transaction.
Persistence Ignorance
POCOs (Plain Old CLR Objects) is “ordinary class where you focus on the business problem at hand without adding stuff for infrastructure-related reasons. … The classes should focus on the business problem at hand. Nothing else should be in the classes in the Domain Model ” – Applying Domain-Driven Design and Patterns: With Examples in C# and .NET, Jimmy Nilsson
a solution based on persistence ignorance generally does better than solution that require infrastructure concerns to be embedded in business objects.
Can the Business Logic Run Independently of the Database ?
one of the most important factors in the success of any software projects is the ability to use rapid feedback cycles.
Some persistence tools will implement transparent lazy loading with the Virtual Proxy pattern to make lazy loading effectively invisible to the business entities themselves. Other tools rely on code generation techniques that embed the lazy-loading support directly into the business entities and effectively create a tight run time coupling from the entities to the persistence infrastructure.
Can I Design My Domain Model Independently from the Database Model ?
referential integrity
An Active Record architecture can simply generates the entity classes from the database structure; a database mapper tool generate a database schema from the entity objects.
How Does My Persistence Strategy Affect My Business Logic ?
The property is marked as virtual for no other reason than to enable NHibernate to create a dynamic proxy for the object that provides a lazy-loaded property.
persistence technologies require a no-argument constructor function.
strict DDD style of entities vs. persistence tools mapping fields, private properties, or constructor function with arguments.
More Units of Work
- The division of resposibility between your Repositories and the Unit of Work.
- How to deliver the correct Unit of Work and the underlying Identity Map helpers to the various classes taking part in a logic transaction.
在这里看到的 Unit of Work 和之前看到的有一些不同,还需要仔细比较一下它们之间区别。