Download - Growing object oriented system
Growing Object-Oriented SystemPrinciples, Guidelines, and Methods
Kent WangDec 6, 2012
13年6月6⽇日星期四
Agenda
• Introduction
• Understand The Problem
• Broad-Brush Design
• Implementation
• Recommended Readings
13年6月6⽇日星期四
Introduction
13年6月6⽇日星期四
Why This Talk
13年6月6⽇日星期四
13年6月6⽇日星期四
Software Developing Is a Learning Process
13年6月6⽇日星期四
Feedback is Critical
Understandthe Problem(Analysis)
Broad-BrushDesign
(Architecture)
Test DrivenDevelopment
(Implementation)
DeployableSystem
13年6月6⽇日星期四
Understand the Problem
13年6月6⽇日星期四
Understand The Problem
• User Story
• Use Case
• Conceptual Model
• Color Modeling
13年6月6⽇日星期四
User Story
Users could pay for their orders from various platform via tenpay
13年6月6⽇日星期四
Use Case
UserPay
13年6月6⽇日星期四
Use Case Is Valuable But Not The End
13年6月6⽇日星期四
Digging A Conceptual Model
13年6月6⽇日星期四
Dig Conceptual Model
Payment
Partner
User
PaymentType
Buyer
Seller
PartnerTrade
13年6月6⽇日星期四
Color Modeling
Moment-Interval
Role
Description
Party / Place /Thing
13年6月6⽇日星期四
User Story Changed
Users could pay for their orders from various platform via tenpay or alipay
13年6月6⽇日星期四
Simple Solution
Payment
Partner
User
PaymentType
Buyer
Seller
PartnerTrade
13年6月6⽇日星期四
The Missing Concept
Payment
Partner
UserPayment
Type
Buyer
Seller
PartnerTrade
ProviderPayment
PaymentProvider
13年6月6⽇日星期四
Models Are Not Right Or Wrong They Are More Or Less Useful
13年6月6⽇日星期四
One Team, One Language
13年6月6⽇日星期四
Bounded Context
Payment
Partner
PaymentType
ProviderPayment
PaymentProvider
13年6月6⽇日星期四
Context Map
ProviderPayment Transaction
unipay tenpayTransaction Map
13年6月6⽇日星期四
Get Help If Required
13年6月6⽇日星期四
Broad-Brush Design
13年6月6⽇日星期四
Broad-Brush Design
• Tackling Complexity
• Architectural Level
• Application Level
• Domain Model Level
13年6月6⽇日星期四
Tackling Complexity
13年6月6⽇日星期四
Separation of Concerns
13年6月6⽇日星期四
Layered Architecture
Application
Presentation
Data Source
13年6月6⽇日星期四
Layered Architecture
Application
Presentation
Data Source
Domain
13年6月6⽇日星期四
High Level of Abstraction
13年6月6⽇日星期四
High Level of Abstraction
13年6月6⽇日星期四
Architectural Level
13年6月6⽇日星期四
Infrastructure
• Distributed or Not
• Synchronous or Asynchronous
• Data Source
13年6月6⽇日星期四
Architectural Style
TransactionScript
Table Module
Domain Model
Complexity
Tool-Chain
13年6月6⽇日星期四
Location of Domain Logic
DAOAO
Domain
vs.
13年6月6⽇日星期四
Concurrent Control
• Transaction is not Silver Bullet
• Optimistic or Pessimistic
• Offline or Not
13年6月6⽇日星期四
Application Level
13年6月6⽇日星期四
Walking Through Scenarios
User Submit Payment
Save PaymentGet Payment Parameter
Submit To Provider
PresentationLayer
ApplicationLayer
13年6月6⽇日星期四
Intension-Revealing Interface
CUnipayAO
GetPaymentParameter
CUnipayAO
ProcessTrade vs.
13年6月6⽇日星期四
Do One Thing
CUnipayAO
GetPaymentParameter
Save or update Payments
Assemble Payment Parameters
13年6月6⽇日星期四
Command Query Separation
System CommandQuery
State A
State B
13年6月6⽇日星期四
Command Query Separation
CUnipayAO
GetPaymentParameter
SetupPaymentSave or update
Payments
Assemble Payment Parameters
13年6月6⽇日星期四
Module
Payment
Payment ProviderPartner
Notification HistorySecurity
Settlement
13年6月6⽇日星期四
Domain Model Level
13年6月6⽇日星期四
Simplify Associations
Payment
Partner
UserPayment
Type
Buyer
Seller
PartnerTrade
ProviderPayment
PaymentProvider
13年6月6⽇日星期四
Simplify Associations
Payment
Partner
PaymentType
PartnerTrade
ProviderPayment
PaymentProvider
13年6月6⽇日星期四
Simplify Associations
Payment
Partner
PaymentType
ProviderPayment
PaymentProvider
1..*
13年6月6⽇日星期四
Simplify Associations
Payment
Partner
PaymentType
ProviderPayment
PaymentProvider
1current
13年6月6⽇日星期四
Design Is Not Just A Technical Issue
13年6月6⽇日星期四
Integrity Problem
ChargePlan
ChargePlanLineItem
ChargePlanLineItem
amount = 50 amount = 50
amount = 100
ChargePlanLineItem
amount = 50
13年6月6⽇日星期四
Aggregate
ChargePlan
ChargePlanLineItem
ChargePlanLineItem
amount = 50 amount = 50
amount = 100
ChargePlanLineItem
amount = 50
13年6月6⽇日星期四
Domain Model Pollution
ao_unipay_settle
PaymentRelay Service
ao_unipay
Transaction
13年6月6⽇日星期四
Anti-Corruption Layer
ao_unipay_settle nao_unipay_tenpay
Tenpay Service Payment
Relay Service
ao_unipay
Transaction
13年6月6⽇日星期四
Design To Test
Tenpay ServiceFacade
Mock Tenpay Relay Client
Tenpay ServiceFacade Test
1. RegisterChargePlan(plan)
3. Execute(request, response)
4. Checking Request5. ReturnResponse
6. Return Response
7. ParseResponse
2. Assemble Request
8. Return Result
9. Checking Result
13年6月6⽇日星期四
Implementation
13年6月6⽇日星期四
Implementation
• Design Tools
• Make A New Type
• Consistent Abstraction Level
• Open Close Principle
• Extract Hidden Concept
13年6月6⽇日星期四
Costly Tools Don’t Produce Better Designs
13年6月6⽇日星期四
UML Without CASE
13年6月6⽇日星期四
CRC CardCTenpayProviderType
Make Tenpay Trade No
Make Tenpay Settle No
Get Request Builder
CTenpayTradeNo
CTenpayProvider
CTenpayRequestBuilder
Class
Respon
sibility
Collaborator
13年6月6⽇日星期四
Duplicated Code// inside NotifyPayment function// inside GetPayment fuction
if (sProviderTradeNo.length() != 28){ return ERR_APP_PARAM_INVALID;}
uint64_t ddwProviderPartnerNo = lexical_cast<uint64_t>(sProviderTradeNo.substr(0, 10))
uint64_t ddwSerialNo = lexical_cast<uint64_t>(sProviderTradeNo.substr(18));
dwRet = GetPaymentByProviderTradeNo( ddwProviderPartnerNo, ddwSerialNo);
13年6月6⽇日星期四
Make A New Type
CTenpayTradeNo
Make Tenpay Trade No
Parse Tenpay Trade No
Verify Tenpay Trade No
CTenpayProvider
Get Date From Trade No
Get Serial No FromTrade No
13年6月6⽇日星期四
Use The New Type
// inside NotifyPayment function// inside GetPayment fuction
CTenpayTradeNo oTradeNo;if (!CProviderTradeNo::TryParse(sProviderTradeNo, oTradeNo){ return ERR_APP_PARAM_INVALID;}
dwRet = GetPaymentByProviderTradeNo( oTradeNo.GetProviderPartnerNo(), oTradeNo.GetProviderTradeSerialNo());
13年6月6⽇日星期四
Too Much Detail// inside SetupPayment function
if (dwRet == ERR_PAYMENT_NOT_FOUND){
CPayment oPayment;oPayment.SetPaymentId(NextPaymentId());oPayment.SetAmount(rTrade.GetAmount());oPayment.SetBuyerUid(rTrade.GetBuyerUid());oPayment.SetSellerUid(rTrade.GetSellerUid());// ... 50 lines more oPayment.SetLastUpdateTime(CTime::Now());
dwRet = m_pDao->SavePayment(oPayment);if (dwRet != 0){ // ... 10 lines of error handling}return dwRet;
}
13年6月6⽇日星期四
Code Closer To Problem
// inside SetupPayment function
if (IsPaymentNotExist(dwRet)){ return CreatePayment();}else{ return MakeSurePriceHasNotChanged();}
13年6月6⽇日星期四
Keep Consistent Abstraction Level
13年6月6⽇日星期四
Feature Envy// inside GetPaymentParameter function
...
if (rProvider.GetType() == TENPAY){ BuildBasicParameter(rPayment); if (rSpec.GetPaymentMethod() == STANDARD) {
BuildParameterOfTenpayStandardPayment(rPayment); } else if (rSpec.GetPaymentMethod() == BANK) { BuildParameterOfTenpayBankPayment(rPayment); }}
...
13年6月6⽇日星期四
Power Of ValuesIPaymentRequestBuilder
Build Payment Request
GetPaymentUrlCopyPaymentParameters
CProviderType
CProvider
CTenpayStandardPaymentRequestBuilder
Build Payment Request
GetPaymentUrl
CopyPaymentParameters
CTenpayProviderType
CTenpayBankPaymentRequestBuilder
Build Payment Request
GetPaymentUrl
CopyPaymentParameters
CTenpayProviderType
13年6月6⽇日星期四
The Clean Way
// inside GetPaymentParameter function
...
IPaymentRequestBuilder* pBuilder = rSpec.GetPaymentMethod().NewPaymentRequestBuilder(rProvider);
pBuilder->Build(rPayment);
...
13年6月6⽇日星期四
Open for ExtensionClose for Modification
13年6月6⽇日星期四
Extract Hidden Concept
// inside NotifyPayment function
...
if (rPayment.GetCurrentProviderPaymentId() == rProviderPayment.GetProviderPaymentId() &&
rPayment.IsWaitPay()){
rPayment.Accept(rProviderPayment);}
...
13年6月6⽇日星期四
Extract Hidden Concept
Payment ProviderPayment
IPaymentAcceptingPolicy
*
13年6月6⽇日星期四
Extract Hidden Concept
// inside NotifyPayment function
IPaymentAcceptingPolicy* paymentAcceptingPolicy;
...
if (paymentAcceptingPolicy->IsAllowedToAccept( rPayment, rProviderPayment))
{rPayment.Accept(rProviderPayment);
}
...
13年6月6⽇日星期四
Making Implicit Concept Explicit
13年6月6⽇日星期四
Recommended Readings
13年6月6⽇日星期四
13年6月6⽇日星期四
13年6月6⽇日星期四
Q & A
13年6月6⽇日星期四
Thanks for your time
13年6月6⽇日星期四