Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Growing Object-Oriented System
Search
Kent Wang
December 10, 2012
Programming
400
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Growing Object-Oriented System
Kent Wang
December 10, 2012
Other Decks in Programming
See All in Programming
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
0
110
エンジニア向け会社紹介/Findy Company Profile
findyinc
6
360k
SREは、MCPとSRE Agentをこう使え!
kazumax55
0
150
ランチタイムLT会3周年!ランチタイムLT会を3年間続けられたお話
y0hgi
1
140
分散システム、なんですぐ死んでしまうん?耐障害性を高めたいあなたのためのレジリエンスパターン入門
mshibuya
7
6.2k
symfony/aiとlaravel/boost
77web
0
130
自作OSでスライド発表する
uyuki234
1
3.8k
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
12
4.8k
関数型プログラミングのメリットって何だろう?
wanko_it
0
180
AIを活用したE2Eテスト実装効率化のあゆみ / ebisu-mobile-14-kotetu
kotetuco
0
170
地域 SRE コミュニティ最前線 - ホンマでっかSRE勉強会
tk3fftk
0
230
才能?センス?知らん、 続けたもん勝ちだ。-- 結婚・出産・癌を越えてなお、私がプロダクトを創り続ける理由
16bitidol
2
860
Featured
See All Featured
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.7k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
320
Raft: Consensus for Rubyists
vanstee
141
7.6k
Marketing to machines
jonoalderson
1
5.6k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.7k
Bash Introduction
62gerente
615
220k
The Limits of Empathy - UXLibs8
cassininazir
1
500
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
250
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
63
55k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
210
Transcript
Growing Object-Oriented System Principles, Guidelines, and Methods Kent Wang Dec
6, 2012
Agenda • Introduction • Understand The Problem • Broad-Brush Design
• Implementation • Recommended Readings
Introduction
Why This Talk
None
Software Developing Is a Learning Process
Feedback is Critical Understand the Problem (Analysis) Broad-Brush Design (Architecture)
Test Driven Development (Implementation) Deployable System
Understand the Problem
Understand The Problem • User Story • Use Case •
Conceptual Model • Color Modeling
User Story Users could pay for their orders from various
platform via tenpay
Use Case User Pay
Use Case Is Valuable But Not The End
Digging A Conceptual Model
Dig Conceptual Model
Dig Conceptual Model Payment
Dig Conceptual Model Payment Partner Trade
Dig Conceptual Model Payment Partner Partner Trade
Dig Conceptual Model Payment Partner User Partner Trade
Dig Conceptual Model Payment Partner User Buyer Seller Partner Trade
Dig Conceptual Model Payment Partner User Payment Type Buyer Seller
Partner Trade
Color Modeling
Color Modeling Moment- Interval
Color Modeling Moment- Interval Party / Place /Thing
Color Modeling Moment- Interval Role Party / Place /Thing
Color Modeling Moment- Interval Role Description Party / Place /Thing
User Story Changed Users could pay for their orders from
various platform via tenpay or alipay
Simple Solution Payment Partner User Payment Type Buyer Seller Partner
Trade
Simple Solution Payment Partner User Payment Type Buyer Seller Partner
Trade
The Missing Concept Payment Partner User Payment Type Buyer Seller
Partner Trade
The Missing Concept Payment Partner User Payment Type Buyer Seller
Partner Trade Provider Payment
The Missing Concept Payment Partner User Payment Type Buyer Seller
Partner Trade Provider Payment Payment Provider
Models Are Not Right Or Wrong They Are More Or
Less Useful
One Team, One Language
Bounded Context Payment Partner Payment Type Provider Payment Payment Provider
Context Map Provider Payment Transaction unipay tenpay
Context Map Provider Payment Transaction unipay tenpay Transaction Map
Get Help If Required
Broad-Brush Design
Broad-Brush Design • Tackling Complexity • Architectural Level • Application
Level • Domain Model Level
Tackling Complexity
Separation of Concerns
Layered Architecture Application Presentation Data Source
Layered Architecture Application Presentation Data Source Domain
High Level of Abstraction
High Level of Abstraction
Architectural Level
Infrastructure • Distributed or Not • Synchronous or Asynchronous •
Data Source
Architectural Style Transaction Script Table Module Domain Model Complexity Tool-Chain
Location of Domain Logic DAO AO vs.
Location of Domain Logic DAO AO Domain vs.
Location of Domain Logic DAO AO Domain vs.
Location of Domain Logic DAO AO Domain vs.
Concurrent Control • Transaction is not Silver Bullet • Optimistic
or Pessimistic • Offline or Not
Application Level
Walking Through Scenarios
Walking Through Scenarios User Submit Payment Save Payment Get Payment
Parameter Submit To Provider
Walking Through Scenarios User Submit Payment Save Payment Get Payment
Parameter Submit To Provider Presentation Layer Application Layer
Intension-Revealing Interface CUnipayAO GetPaymentParameter CUnipayAO ProcessTrade vs.
Do One Thing CUnipayAO GetPaymentParameter
Do One Thing CUnipayAO GetPaymentParameter Save or update Payments Assemble
Payment Parameters
Command Query Separation System Command Query State A
Command Query Separation System Command Query State B
Command Query Separation System Command Query State B
Command Query Separation CUnipayAO GetPaymentParameter SetupPayment Save or update Payments
Assemble Payment Parameters
Module Payment Payment Provider Partner Notification History Security Settlement
Domain Model Level
Simplify Associations Payment Partner User Payment Type Buyer Seller Partner
Trade Provider Payment Payment Provider
Simplify Associations Payment Partner Payment Type Partner Trade Provider Payment
Payment Provider
Simplify Associations Payment Partner Payment Type Provider Payment Payment Provider
1..*
Simplify Associations Payment Partner Payment Type Provider Payment Payment Provider
1 current
Design Is Not Just A Technical Issue
Integrity Problem ChargePlan ChargePlan LineItem ChargePlan LineItem amount = 50
amount = 50 amount = 100
Integrity Problem ChargePlan ChargePlan LineItem ChargePlan LineItem amount = 50
amount = 50 amount = 100 ChargePlan LineItem amount = 50
Aggregate ChargePlan ChargePlan LineItem ChargePlan LineItem amount = 50 amount
= 50 amount = 100
Aggregate ChargePlan ChargePlan LineItem ChargePlan LineItem amount = 50 amount
= 50 amount = 100 ChargePlan LineItem amount = 50
Domain Model Pollution ao_unipay_settle Payment Relay Service ao_unipay Transaction
Anti-Corruption Layer ao_unipay_settle nao_unipay_tenpay Tenpay Service Payment Relay Service ao_unipay
Transaction
Design To Test Tenpay Service Facade
Design To Test Tenpay Service Facade Mock Tenpay Relay Client
Tenpay Service Facade Test
Design To Test Tenpay Service Facade Mock Tenpay Relay Client
Tenpay Service Facade Test 1. RegisterChargePlan(plan) 3. Execute(request, response) 4. Checking Request 5. Return Response 6. Return Response 7. Parse Response 2. Assemble Request 8. Return Result 9. Checking Result
Implementation
Implementation • Design Tools • Make A New Type •
Consistent Abstraction Level • Open Close Principle • Extract Hidden Concept
Costly Tools Don’t Produce Better Designs
UML Without CASE
CRC Card CTenpayProviderType Make Tenpay Trade No Make Tenpay Settle
No Get Request Builder CTenpayTradeNo CTenpayProvider CTenpayRequest Builder
CRC Card CTenpayProviderType Make Tenpay Trade No Make Tenpay Settle
No Get Request Builder CTenpayTradeNo CTenpayProvider CTenpayRequest Builder Class Responsibility Collaborator
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);
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 From Trade No
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());
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; }
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; }
Code Closer To Problem // inside SetupPayment function if (IsPaymentNotExist(dwRet))
{ return CreatePayment(); } else { return MakeSurePriceHasNotChanged(); }
Code Closer To Problem // inside SetupPayment function if (IsPaymentNotExist(dwRet))
{ return CreatePayment(); } else { return MakeSurePriceHasNotChanged(); }
Keep Consistent Abstraction Level
Feature Envy // inside GetPaymentParameter function ... if (rProvider.GetType() ==
TENPAY) { BuildBasicParameter(rPayment); if (rSpec.GetPaymentMethod() == STANDARD) { BuildParameterOfTenpayStandardPayment(rPayment); } else if (rSpec.GetPaymentMethod() == BANK) { BuildParameterOfTenpayBankPayment(rPayment); } } ...
Feature Envy // inside GetPaymentParameter function ... if (rProvider.GetType() ==
TENPAY) { BuildBasicParameter(rPayment); if (rSpec.GetPaymentMethod() == STANDARD) { BuildParameterOfTenpayStandardPayment(rPayment); } else if (rSpec.GetPaymentMethod() == BANK) { BuildParameterOfTenpayBankPayment(rPayment); } } ...
Power Of Values IPaymentRequestBuilder Build Payment Request GetPaymentUrl CopyPaymentParameters CProviderType
CProvider CTenpayStandardPayment RequestBuilder Build Payment Request GetPaymentUrl CopyPaymentParameters CTenpayProviderType CTenpayBankPayment RequestBuilder Build Payment Request GetPaymentUrl CopyPaymentParameters CTenpayProviderType
The Clean Way // inside GetPaymentParameter function ... IPaymentRequestBuilder* pBuilder
= rSpec.GetPaymentMethod(). NewPaymentRequestBuilder(rProvider); pBuilder->Build(rPayment); ...
Open for Extension Close for Modification
Extract Hidden Concept // inside NotifyPayment function ... if (rPayment.GetCurrentProviderPaymentId()
== rProviderPayment.GetProviderPaymentId() && rPayment.IsWaitPay()) { rPayment.Accept(rProviderPayment); } ...
Extract Hidden Concept // inside NotifyPayment function ... if (rPayment.GetCurrentProviderPaymentId()
== rProviderPayment.GetProviderPaymentId() && rPayment.IsWaitPay()) { rPayment.Accept(rProviderPayment); } ...
Extract Hidden Concept Payment ProviderPayment IPaymentAcceptingPolicy *
Extract Hidden Concept // inside NotifyPayment function IPaymentAcceptingPolicy* paymentAcceptingPolicy; ...
if (paymentAcceptingPolicy->IsAllowedToAccept( rPayment, rProviderPayment)) { rPayment.Accept(rProviderPayment); } ...
Extract Hidden Concept // inside NotifyPayment function IPaymentAcceptingPolicy* paymentAcceptingPolicy; ...
if (paymentAcceptingPolicy->IsAllowedToAccept( rPayment, rProviderPayment)) { rPayment.Accept(rProviderPayment); } ...
Making Implicit Concept Explicit
Recommended Readings
None
None
Q & A
Thanks for your time