MSDN Magazine - February 2009 - (Page 51) Figure 2 Using Read-Only to Enforce Immutability public class Money { public readonly Currency Currency; public readonly decimal Amount; public Money(decimal amount, Currency currency) { Amount = amount; Currency = currency; } public Money AddFunds(Money fundsToAdd) { // because the money we're adding might // be in a different currency, we'll service // locate a money exchange Domain Service. var exchange = ServiceLocator.Find (); var normalizedMoney = exchange.CurrentValueFor(fundsToAdd, this.Currency); var newAmount = this.Amount + normalizedMoney.Amount; return new Money(newAmount, this.Currency); } of $40. In C# you can use the read-only keyword on public fields to enforce immutability and side-effect-free functions, as shown in Figure 2. Aggregate Roots Combine Entities } public enum Currency { USD, GBP, EUR, JPY } Value Objects Describe Things Value objects are descriptors or properties important in the domain you are modeling. Unlike entities, they do not have an identity; they simply describe the things that do have identities. Are you changing an entity called “Thirty-Five Dollars” or are you incrementing the balance of an account? Part of the beauty of value objects is that they describe the properties of entities in a much more elegant and intention-revealing way. Money, a common value object, looks a lot better as a function parameter on a funds transfer API than a decimal does. When you spot it in an interface or entity method, you know what you’re dealing with right away. Value objects are immutable. They are incapable of change once they are created. Why is it important that they be immutable? With value objects, you’re seeking side-effect-free functions, yet another concept borrowed by DDD. When you add $20 to $20, are you changing $20? No, you are creating a new money descriptor Figure 3 Testing Aggregate Roots public class When_renewing_an_active_policy_that_needs_renewal { Policy ThePolicy; DateTime OriginalEndingOn; [SetUp] public void Context() { ThePolicy = new Policy(new DateTime(1/1/2009)); var somePayroll = new CompanyPayroll(); ThePolicy.Covers(somePayroll); ThePolicy.Write(); OriginalEndingOn = ThePolicy.EndingOn; } [Test] public void Should_create_a_new_period() { ThePolicy.EndingOn.ShouldEqual(OriginalEndingOn.AddYears(1)); } An aggregate root is a special kind of entity that consumers refer to directly. Identifying aggregate roots allows you to avoid overcoupling the objects that comprise your model by imposing a few simple rules. You should note that aggregate roots guard their subentities zealously. The biggest rule to keep in mind is that aggregate roots are the only kind of entity to which your software may hold a reference. This helps avoid The Big Ball of Mud because you now have a constraint that prevents you from creating a tightly coupled system where everything has an association to everything else. Let’s assume I have an entity called Policy. Well, policies get renewed on an annual term, so there’s likely an entity called Period. Since a Period cannot exist without a Policy and you can act on Periods through Policy, Policy is said to be an aggregate root and Period is a child of the same. I like my aggregate roots to just figure it out for me. Consider this consumer code accessing a Policy aggregate root: Policy.CurrentPeriod().Renew() I’m trying to renew an insurance policy—recall the class diagram of the core domain of insurance policy management. Note how I’m dotting my way to the behavior I want to invoke? There are a couple of problems with this approach. First, I’m clearly violating the Law of Demeter. A method M of an object O should invoke only the methods of the following kinds of objects: itself, its parameters, any objects it creates or instantiates, or its direct component objects. Isn’t deep dotting kind of convenient? IntelliSense is one of the coolest, most useful features of Visual Studio and other modern IDEs, but when you start dotting your way to the function you actually want to invoke, you’re introducing unnecessary coupling into the system. In the previous example, I’m now dependent upon the Policy class and the Period class. For further reading, Brad Appleton has an excellent article available on his site that explains the deeper implications, theories, tooling and caveats around the Law of Demeter (cmcrossroads.com/ bradapp/docs/demeter-intro.html). The cliche “death by a thousand cuts” is a good description of the potential maintenance nightmare of an overly coupled system. When you create unnecessary references all over the place, you also create a rigid model where changes in one place result in a cascade of changes all over consumer code. You could accomplish the same goal with, as far as I’m concerned, a much more expressive bit of code: Policy.Renew() } See how the aggregate just figures it out? Internally it can find the current period and whether or not there’s already a renewal period and whatever else you need it to do. I find that when I’m unit testing my aggregate roots using a technique such as Behavior-Driven Development (BDD), my tests trend February 2009 51 msdnmagazine.com http://www.cmcrossroads.com/bradapp/docs/demeter-intro.html http://www.cmcrossroads.com/bradapp/docs/demeter-intro.html http://www.msdnmagazine.com
Table of Contents Feed for the Digital Edition of MSDN Magazine - February 2009 MSDN Magazine - February 2009 Contents Toolbox CLR Inside Out Data Points Cutting Edge Patterns In Practice Best Practices .Net Interop "Oslo" Basics Patterns Silverlight Under The Table Foundations Windows With C++ .NET Matters Going Places { End Bracket } MSDN Magazine - February 2009 MSDN Magazine - February 2009 - (Page Splash1) MSDN Magazine - February 2009 - Contents (Page Cover1) MSDN Magazine - February 2009 - Contents (Page Cover2) MSDN Magazine - February 2009 - Contents (Page 1) MSDN Magazine - February 2009 - Contents (Page 2) MSDN Magazine - February 2009 - Contents (Page 3) MSDN Magazine - February 2009 - Contents (Page 4) MSDN Magazine - February 2009 - Contents (Page 5) MSDN Magazine - February 2009 - Contents (Page 6) MSDN Magazine - February 2009 - Contents (Page 7) MSDN Magazine - February 2009 - Contents (Page 8) MSDN Magazine - February 2009 - Contents (Page 9) MSDN Magazine - February 2009 - Contents (Page 10) MSDN Magazine - February 2009 - Toolbox (Page 11) MSDN Magazine - February 2009 - Toolbox (Page 12) MSDN Magazine - February 2009 - Toolbox (Page 13) MSDN Magazine - February 2009 - Toolbox (Page 14) MSDN Magazine - February 2009 - CLR Inside Out (Page 15) MSDN Magazine - February 2009 - CLR Inside Out (Page 16) MSDN Magazine - February 2009 - CLR Inside Out (Page 17) MSDN Magazine - February 2009 - CLR Inside Out (Page 18) MSDN Magazine - February 2009 - CLR Inside Out (Page 19) MSDN Magazine - February 2009 - CLR Inside Out (Page 20) MSDN Magazine - February 2009 - CLR Inside Out (Page 21) MSDN Magazine - February 2009 - CLR Inside Out (Page 22) MSDN Magazine - February 2009 - Data Points (Page 23) MSDN Magazine - February 2009 - Data Points (Page 24) MSDN Magazine - February 2009 - Data Points (Page 25) MSDN Magazine - February 2009 - Data Points (Page 26) MSDN Magazine - February 2009 - Data Points (Page 27) MSDN Magazine - February 2009 - Data Points (Page 28) MSDN Magazine - February 2009 - Data Points (Page 29) MSDN Magazine - February 2009 - Data Points (Page 30) MSDN Magazine - February 2009 - Cutting Edge (Page 31) MSDN Magazine - February 2009 - Cutting Edge (Page 32) MSDN Magazine - February 2009 - Cutting Edge (Page 33) MSDN Magazine - February 2009 - Cutting Edge (Page 34) MSDN Magazine - February 2009 - Cutting Edge (Page 35) MSDN Magazine - February 2009 - Cutting Edge (Page 36) MSDN Magazine - February 2009 - Cutting Edge (Page 37) MSDN Magazine - February 2009 - Cutting Edge (Page 38) MSDN Magazine - February 2009 - Patterns In Practice (Page 39) MSDN Magazine - February 2009 - Patterns In Practice (Page 40) MSDN Magazine - February 2009 - Patterns In Practice (Page 41) MSDN Magazine - February 2009 - Patterns In Practice (Page 42) MSDN Magazine - February 2009 - Patterns In Practice (Page 43) MSDN Magazine - February 2009 - Patterns In Practice (Page 44) MSDN Magazine - February 2009 - Patterns In Practice (Page 45) MSDN Magazine - February 2009 - Best Practices (Page 46) MSDN Magazine - February 2009 - Best Practices (Page 47) MSDN Magazine - February 2009 - Best Practices (Page 48) MSDN Magazine - February 2009 - Best Practices (Page 49) MSDN Magazine - February 2009 - Best Practices (Page 50) MSDN Magazine - February 2009 - Best Practices (Page 51) MSDN Magazine - February 2009 - Best Practices (Page 52) MSDN Magazine - February 2009 - Best Practices (Page 53) MSDN Magazine - February 2009 - Best Practices (Page 54) MSDN Magazine - February 2009 - Best Practices (Page 55) MSDN Magazine - February 2009 - Best Practices (Page 56) MSDN Magazine - February 2009 - .Net Interop (Page 57) MSDN Magazine - February 2009 - .Net Interop (Page 58) MSDN Magazine - February 2009 - .Net Interop (Page 59) MSDN Magazine - February 2009 - .Net Interop (Page 60) MSDN Magazine - February 2009 - .Net Interop (Page 61) MSDN Magazine - February 2009 - .Net Interop (Page 62) MSDN Magazine - February 2009 - "Oslo" Basics (Page 63) MSDN Magazine - February 2009 - "Oslo" Basics (Page 64) MSDN Magazine - February 2009 - "Oslo" Basics (Page 65) MSDN Magazine - February 2009 - "Oslo" Basics (Page 66) MSDN Magazine - February 2009 - "Oslo" Basics (Page 67) MSDN Magazine - February 2009 - "Oslo" Basics (Page 68) MSDN Magazine - February 2009 - "Oslo" Basics (Page 69) MSDN Magazine - February 2009 - "Oslo" Basics (Page 70) MSDN Magazine - February 2009 - "Oslo" Basics (Page 71) MSDN Magazine - February 2009 - Patterns (Page 72) MSDN Magazine - February 2009 - Patterns (Page 73) MSDN Magazine - February 2009 - Patterns (Page 74) MSDN Magazine - February 2009 - Patterns (Page 75) MSDN Magazine - February 2009 - Patterns (Page 76) MSDN Magazine - February 2009 - Patterns (Page 77) MSDN Magazine - February 2009 - Patterns (Page 78) MSDN Magazine - February 2009 - Patterns (Page 79) MSDN Magazine - February 2009 - Patterns (Page 80) MSDN Magazine - February 2009 - Patterns (Page 81) MSDN Magazine - February 2009 - Patterns (Page 82) MSDN Magazine - February 2009 - Patterns (Page 83) MSDN Magazine - February 2009 - Silverlight (Page 84) MSDN Magazine - February 2009 - Silverlight (Page 85) MSDN Magazine - February 2009 - Silverlight (Page 86) MSDN Magazine - February 2009 - Silverlight (Page 87) MSDN Magazine - February 2009 - Silverlight (Page 88) MSDN Magazine - February 2009 - Silverlight (Page 89) MSDN Magazine - February 2009 - Silverlight (Page 90) MSDN Magazine - February 2009 - Silverlight (Page 91) MSDN Magazine - February 2009 - Silverlight (Page 92) MSDN Magazine - February 2009 - Silverlight (Page 93) MSDN Magazine - February 2009 - Silverlight (Page 94) MSDN Magazine - February 2009 - Under The Table (Page 95) MSDN Magazine - February 2009 - Under The Table (Page 96) MSDN Magazine - February 2009 - Under The Table (Page 97) MSDN Magazine - February 2009 - Under The Table (Page 98) MSDN Magazine - February 2009 - Under The Table (Page 99) MSDN Magazine - February 2009 - Under The Table (Page 100) MSDN Magazine - February 2009 - Foundations (Page 101) MSDN Magazine - February 2009 - Foundations (Page 102) MSDN Magazine - February 2009 - Foundations (Page 103) MSDN Magazine - February 2009 - Foundations (Page 104) MSDN Magazine - February 2009 - Foundations (Page 105) MSDN Magazine - February 2009 - Foundations (Page 106) MSDN Magazine - February 2009 - Windows With C++ (Page 107) MSDN Magazine - February 2009 - Windows With C++ (Page 108) MSDN Magazine - February 2009 - Windows With C++ (Page 109) MSDN Magazine - February 2009 - Windows With C++ (Page 110) MSDN Magazine - February 2009 - .NET Matters (Page 111) MSDN Magazine - February 2009 - .NET Matters (Page 112) MSDN Magazine - February 2009 - .NET Matters (Page 113) MSDN Magazine - February 2009 - .NET Matters (Page 114) MSDN Magazine - February 2009 - Going Places (Page 115) MSDN Magazine - February 2009 - Going Places (Page 116) MSDN Magazine - February 2009 - Going Places (Page 117) MSDN Magazine - February 2009 - Going Places (Page 118) MSDN Magazine - February 2009 - Going Places (Page 119) MSDN Magazine - February 2009 - { End Bracket } (Page 120) MSDN Magazine - February 2009 - { End Bracket } (Page Cover3) MSDN Magazine - February 2009 - { End Bracket } (Page Cover4)
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.