Growing object oriented system

Preview:

Citation preview

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⽇日星期四

Recommended