jimmy nilsson - patterns - Øredevarchive.oredev.org/.../jimmy_nilsson_-_patterns.pdf · author of...
TRANSCRIPT
About Jimmy Nilsson
Primarily a developer, but also a trainer and author
Blogs at www.jnsk.se/weblog/
Author of ”Applying Domain-Driven Design and Patterns” and ”.NET Enterprise Design”
Agenda
• Short introduction
• Problem 1: Location of persistence code
• Problem 2: Queries against a domain model
• Problem 3: Maintenance of a state graph
• Bonus: Non-trivial instantiation
What’s a pattern?A design pattern hasName
Problem (including context)
Solution
Consequences
Nothing but simple, flexible and elegant solutions
When to use patterns?
• Don’t design a new application using all the patterns you can think of
• Start as simple as possible
• Introduce patterns as required
*
Problem 1: Location of Persistence code
We’d like to persist information about customers and orders
Customer Order
Solution 1A: Save() etc on the Entities
Ouch... Hard to control transactions. And not too true to the Single Responsibility Principle
(But Active Record [PoEAA] has definitely got a new life...)
*
Customer
------------------------
Id
Name
-----------------------
DoStuff()
Save()
Find(id):Customer
Order
------------------------
Id
-----------------------
DoOtherStuff()
Save()
Find(id):Order
Solution 1B: Unit of Work+Identity Map [PoEAA]
Ouch... Too much responsibility on the client?
+RegisterNew(in object)
+RegisterDirty(in object)
+RegisterClean(in object)
+RegisterDeleted(in object)
+Commit()
UnitOfWork finder an identity map database
Find(1)
found = Get(1)
[found not null] found
[found is null] found = select ... where id = 1
Solution 1C: Repository [DDD]
client repository database
selection criteria
matching objects Delegate
Pause: Gregg Irwin said this about pattern adoption
1. You use it without being aware that you’re using it
2. You hear about it, read up on it, and tinker a bit
3. You learn more and start using it explicitly, if naively
4. You get the fire and evangelize (optional)
5. Something ”clicks”
6. You learn more and apply it ”less naively” and more implicitly
7. Time passes and you see flaws
8. You question the concept (often because you misapplied it)
9. You either forget about it or add knowledge and experience(Repeat steps 5-9 if necessary)
10. You use it without being aware that you are using it
*
Problem 2: Queries against a domain model
Send letter to all customers who have a credit limit > 1'' and who have bought from a certain product group the last month
Customer Order
Solution 2A: Loop
Ouch... A relational database is used, instantiation of all customers and orders in the domain model is too ”expensive”
Solution 2B: Query Object [PoEAA]
Ouch... Too much responsibility
on the client?
Query
1*
-_operator
-_field
-_value
Criteria
Solution 2C: Repository [DDD]
Ouch... The repository classes may grow very large. And this isn’t taking care of the situation when you’d like to check a transient customer
client repository database
selection criteria
matching objects Delegate
Solution 2D: Specification [DDD]
+...()
+IsDelinquent() : bool
Invoice
+...()
Invoice
+Test(in invoice) : bool
InvoiceDelinquency
Solution 3A: if-statements everywhere
Ouch... The description of the graph is very mixed up and spread out
Solution 3B: A table based representation of the graph
Ouch... Hard to elegantly deal with state specific behavior
Solution 3C: State [GoF]
+Request()
Context
+Handle()
State
+Handle()
ConcreteStateA
+Handle()
ConcreteStateB
-_state
_state.Handle()
Bonus: Non-trivial instantiation
An order can be instantiated as:
New ordinary
New reservation
New credit order
New repetition
Fetch stored order
Bonus B: Static methods
Ouch... The class has two different responsibilities(Even if we factor out the fetching of a stored instance)
ReferencesGamma, Helm, Johnson, Vlissides: Design Patterns [GoF]
Evans: Domain-Driven Design [DDD]
Fowler: Patterns of Enterprise Application Architecture [PoEAA]
Fowler: Refactoring [R]
Kerievsky: Refactoring to Patterns [R2P]
Nilsson: Applying Domain-Driven Design and Patterns [ADDDP]