1 / 40

Domain-driven Design

Domain-driven Design. (book by Eric Evans) Part of the system is a “domain model” Customers and developers share “ubiquitous language”, which is expressed in domain model You understand the problem best on the last day of the project, which is why the domain model keeps changing. Patterns.

janae
Télécharger la présentation

Domain-driven Design

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Domain-driven Design • (book by Eric Evans) • Part of the system is a “domain model” • Customers and developers share “ubiquitous language”, which is expressed in domain model • You understand the problem best on the last day of the project, which is why the domain model keeps changing

  2. Patterns • People don’t design from first principles. • People design by reusing ideas they have seen before • From previous projects • From books, courses, etc

  3. What Really is an Object? • Relationship can be an object if it has attributes and relationships • Marriage has duration and children • Intersection has accidents • Attribute can be an object if it has attributes • Temperature is taken at a point in time

  4. What Really is an Object? • Reservation -- a promise to give service to a customer • Ticket -- record the event of the customer paying for service in advance, • Flight -- an event in which an airplane provides service • Payment -- an event (transaction?) in which money is exchanged

  5. Attributes are simpler than objects. • Associations are simpler than objects. • Models should be as simple as possible, but no simpler.

  6. Why this is important • Many of the objects in a good design are NOT problem domain objects. • Example: ValueWithHistory • They can represent operations, processes, states, constraints, relationships, ...

  7. Design for Reuse • Purpose is to make a system flexible, extensible, and easily changed. • Make things objects if they need to be changed and manipulated.

  8. Design for Reuse • Goal is to build an application just by using preexisting objects. • Compose, don't program. • Relationship between objects as important as class hierarchy.

  9. Refactoring

  10. Piecemeal Growth • The way living things grow • The way software grows • More than just addition -- transformation

  11. http://c2.com/cgi/wiki?ExtremeNormalForm • Your classes are small and your methods are small; you've said everything OnceAndOnlyOnce and you've removed the last piece of unnecessary code. • Somewhere far away an Aikido master stands in a quiet room. He is centered.. aware.. ready for anything. • Outside a sprinter shakes out her legs and settles into the block, waiting for the crack of the gun while a cool wind arches across the track. • Softly, a bell sounds.. all of your tests have passed. • Your code is in ExtremeNormalForm.. tuned to today and poised to strike at tomorrow.

  12. Extreme Normal Form Defined • All the code is tested. The code passes all the tests. • No one on the team can think of code in the system that they could remove or simplify without reducing the feature set. • You never have to go more than one place to change one thing.

  13. Refactoring • Extreme Normal Form is a result of refactoring • Refactoring: changes to the organization of a program, not its function. • Behavior preserving program transformations.

  14. Why refactoring is important • Only defense against software decay. • Often needed to fix reusability bugs. • Lets you add patterns after you have written a program; lets you transform program into framework. • Lets you worry about generality tomorrow; just get it working today. • Necessary for beautiful software.

  15. Refactoring • Refactoring: Improving the Design of Existing Code by Martin Fowler with contributions by Kent Beck, John Brant, William Opdyke, and Don Roberts, Addison-Wesley 1999 • www.refactoring.com

  16. How to refactor • Make changes as small as possible. • Test after each change. • Many small changes are easier than one big change. • Each change makes it easier to see that more changes are needed.

  17. How to Refactor • Use Sunit to write test suite • Use TestRunner to run it; “keep your light green”. • Plan change so it is a series of small refactoring. • Run tests after every refactoring, once every 5 minutes.

  18. Example: Strategy • Initially: class C with public method m • 1) Make a Strategy class S with empty method mFor: • 2) Add instance variable “strategy” to C, initialize it with an instance of S, and change m to have “strategy mFor: self” • 3) Move code from m to mFor: • 4) Move private methods from C to S.

  19. Refactoring browser • A better browser • Automates many refactorings - renaming, moving code, splitting • Undo • Lint helps you find places that need to be refactored.

  20. Code Smells • Data class • Switch statements • Speculative generality • Temporary field • Refused bequest Duplicated code Long method Large class Long parameter list Message chain Feature envy

  21. Duplicate code • Eliminate duplication by • making new methods • making new objects • moving methods to common superclass

  22. Long methods • Each method should do one thing. • One comment for each method. • Method should fit on the screen. • Method is all on same level of abstraction. • Method should be in right class.

  23. FileSystemHandler • directoryResponse: aDirectory • self indexFileNames • do: [:each | indexFile | • indexFile := aDirectory construct: each. indexFile safeIsReadable • ifTrue: [^FileResponse fileNamed: indexFile]]. • ^DirectoryResponse fileNamed: aDirectory in: self • indexFileNames • ^#('index.html' 'index.htm' 'default.html' 'default.htm')

  24. FileSystemHandler • directoryResponse: aDirectory • (self indexFilesFor: aDirectory) • do: [:indexFile | indexFile safeIsReadable • ifTrue: [^FileResponse fileNamed: indexFile]]. • ^DirectoryResponse fileNamed: aDirectory in: self • indexFilesFor: aDirectory • ^#('index.html' 'index.htm' 'default.html' 'default.htm') • collect: [:each | aDirectory construct: each]

  25. Long method in CompositeWiki • responseKeyFor: aRequest • | mightNotBeTheRightPlace key | • mightNotBeTheRightPlace := aRequest identifier size >= self depth. • mightNotBeTheRightPlace • ifTrue: [key := aRequest identifier at: self depth] • ifFalse: • [^aRequest postDataAt: #COMMAND • ifAbsent: [aRequest postDataAt: #DEFAULT_COMMAND ifAbsent: [self rootKey]]]. • (self containsAction: key) • ifTrue: [aRequest decodeUrlencodedFormData: aRequest lastIdentifier]. • ^key

  26. Method in CompositeWiki • responseKeyFor: aRequest • aRequest identifier size < self depth • ifTrue: • [^aRequest postDataAt: #COMMAND ifAbsent: • [aRequest postDataAt: #DEFAULT_COMMAND ifAbsent: • [self rootKey]]]. • (self containsAction: (self keyIn: aRequest)) • ifTrue: [aRequest decodeUrlencodedFormData: aRequest lastIdentifier]. • ^self keyIn: aRequest

  27. responseKeyFor: aRequest • (aRequest isKeyMissingFor: self) • ifTrue: • [^aRequest postDataAt: #COMMAND ifAbsent: • [aRequest postDataAt: #DEFAULT_COMMAND ifAbsent: • [self rootKey]]]. • (self containsAction: (self keyIn: aRequest)) • ifTrue: [aRequest decodeUrlencodedFormData: aRequest lastIdentifier]. • ^self keyIn: aRequest

  28. Data class • Some classes have only variables and accessors. • Look for places where accessors are used and eliminate “feature envy” and “message chains”.

  29. Feature Envy • teacher classes add: thisClass. • teacher classLoad: (teacher classLoad + 1) • teacher addClass: thisClass

  30. Message chain • Eliminate navigation code • Ensures that user of an object doesn’t have to know many classes • aFigure boundingBox center

  31. Message chain • Law of Demeter: • Method should only send messages to classes of instance variables and arguments. • anX m1 m2 m3 m4 m5 m6 => anX m6

  32. Large classes • More than seven or eight variables • More than fifty methods • You probably need to break up the class • Components (Strategy, Composite, Decorator) • Inheritance

  33. Long parameter lists • If you see the same set of parameters repeated in several methods, bundle them into a new object. Create accessers to get the original parameters from the object. Change the methods to use the new object instead of the parameters. • Then figure out what other functionality needs to move to the object.

  34. Case Statements • Use polymorphism, not case statement. • Make class hierarchy, one class for each case. • Make a method for each case statement. • Make each branch of case statement be a method in a class

  35. Refused bequest • Subclass does not use all the inherited methods. • Overrides methods with different algorithm • Overrides methods with error message • Solution: • Make a new superclass

  36. Refused Bequest A doX doY C doY B doX B doX A doX

  37. Temporary field • Instance variable is only used during part of the lifetime of an object. • For example, it is only used while the object is initialized. • Move variable into another object

  38. Non-localized plan • Adding a feature requires a plan. If adding a feature requires changing many parts of a program, it is called a “non-localized plan”. • Parallel class hierarchies: adding a class in one class hierarchy requires adding a class in another • Example: a new view class requires a new controller class

  39. How to refactor non-localized plan • Make a new object that represents everything that changes. • Methods that change together should stay together.

  40. When to refactor • If a new feature seems hard to implement, refactor. • If a new feature created some ugly code, refactor. • When you can’t stand to look at your code, refactor.

More Related