15
So We Thought We Knew Money Ying Hu Sam Peng [email protected] [email protected] Custom House Global Foreign Exchange

So We Thought We Knew Money

  • Upload
    ying

  • View
    999

  • Download
    0

Embed Size (px)

DESCRIPTION

Experience report on applying DDD to discover and refactor domain fundamental value objects

Citation preview

Page 1: So We Thought We Knew Money

So We Thought We Knew Money

Ying Hu Sam [email protected] [email protected]

Custom House Global Foreign Exchange

Page 2: So We Thought We Knew Money

Outline

• Background• The problem in the system• Distilling the domain model and the discovery

of the value objects• Refactoring, differences before and after• Compromises and pitfalls

Page 3: So We Thought We Knew Money

The Domain

• Foreign exchange is all we do

Page 4: So We Thought We Knew Money

In our system…

• Variable names of primitive data types public class Contract { decimal tradingRate; bool isRateDirect; string tradeCurrency; decimal tradeAmount; string settlementCurrency; decimal settlementAmount; decimal Markup; … …

decimal GetRate(string unitCurrency, string referenceCurrency);

• Method names, parameters, return types

Page 5: So We Thought We Knew Money

Implicit Domain ConceptPublic Class Contract{ decimal CalculateSettlementAmount(

bool isRateDirect,decimal tradeAmount,decimal tradingRate)

{if (isRateDirect)

return tradeAmount * tradingRate;else

return tradeAmount / tradingRate; }

decimal settlementAmount = CalculateSettlementAmount(true, 200m, 1.12m);

//……}

Public Class Contract{ decimal ApplyMarkup( decimal rate, decimal markup, bool isPercentageMarkup, bool isBuyMarkup) { if (isBuyMarkup) { if (isPercentageMarkup)

return rate* (1-markup); else

return rate-markup; } else { if (isPercentageMarkup)

return rate* (1+markup); else

return rate+markup; } }

decimal newRate = ApplyMarkup(1.12, 0.02, true, false);

}

Page 6: So We Thought We Knew Money

Distilling the Domain

• Domain Driven Design– Excessive use of primitive data types– Lack of ubiquitous language

• Distilling Domain Model (phase one)– Discovery of domain fundamental value objects– Refactoring

Page 7: So We Thought We Knew Money

Value Objects - Rate • Encapsulate domain logicClass Contract{ decimal CalculateSettlementAmount(

bool isRateDirect,decimal tradeAmount,decimal tradingRate)

{if (isRateDirect)

return tradeAmount * tradingRate;else

return tradeAmount / tradingRate;

}

// …….

decimal settlementAmount =CalculateSettlementAmount(true, 200m, 1.12m);

Class Rate{ Currency unitCurrency; Currency settlementCurrency; decimal value; public Money Convert (Money money);}

Class Contract { Money settlementMoney = tradingRate.Convert(tradeMoney);}

Page 8: So We Thought We Knew Money

Class Contract

public decimal ApplyMarkup( decimal rate, decimal markup, bool isPercentageMarkup, bool isBuyMarkup){ if (isBuyMarkup) { if (isPercentageMarkup)

return rate* (1-markup); else

return rate-markup; } else { if (isPercentageMarkup)

return rate* (1+markup); else

return rate+markup; }}

decimal newRate = ApplyMarkup(1.12, 0.02, true, false);

Value Objects - Markup

Class Markup

public Rate AppliedTo(Rate rate);

Class Contract

Rate newRate = markup.AppliedTo(oldRate);

Page 9: So We Thought We Knew Money

Value Objects

• Simplifying interfacespublic decimal CalculateProfit(

string tradeCurrency, decimal tradeAmount,string settlementCurrency, decimal settlementAmount )

public Money CalculateProfit(money tradeMoney, money settlementMoney)

• Type safedecimal GetRate(

string unitCurrency,string referenceCurrency);

Rate GetRate(Currency unitCurrency,Currency referenceCurrency);

Currency gbp = CurrencyList.Get(“GBP”);

Page 10: So We Thought We Knew Money

Refactoring

• Shared code base (CVS)• Unit test suites• Continuous integration• 2 developers working on refactoring, others

working on upcoming release• 2 weeks to redesign and refactor• Tool: Jetbrain’s Resharper

Page 11: So We Thought We Knew Money

Compromises…• Refactor important interfaces

public class Order{ private decimal settlementAmount; private string settlementCurrency;

public string SettlementCurrency { get { return settlementCurrency; } }

public decimal SettlementAmount { get { return settlementAmount;} }}

public class Order{ private decimal settlementAmount; private string settlementCurrency;

public Money SettlementMoney { get{ return new Money(settlementCurrency,settlementAmount); } }}

Page 12: So We Thought We Knew Money

…And Pitfallspublic class Rate{

public static implicit operator decimal(Rate rate){

return rate.Value;}

public Money AddMoney(Money target, Money moneyToAdd) {

return target + Convert(moneyToAdd); }

}

X

Page 13: So We Thought We Knew Money

Today and Beyond

• More domain fundamental objects are discovered.

• More interfaces and classes have been refactored

• Richer, evolving domain model• Confidence and skills to refactor

Page 14: So We Thought We Knew Money

Summary

• Domain Driven Design: make hidden domain concept explicit– http://www.domaindrivendesign.com

• A concrete example of refactoring: replacing primitive types with value objects.

• Share our experiences as well as pitfalls.

Page 15: So We Thought We Knew Money

Thank you for your attention

• IAnticorruption – A Domain Driven Approach To More Robust Integration

by Sam Peng and Ying Hu