Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
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
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
180
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
170
一人だけ、Kiroが静止する日
hideg
0
120
Go × SIMDで高速化するベクトル検索 ~ルーフラインモデルでSIMDが効く境界を探れ! ~
po3rin
1
1.7k
ゲームコントローラやキーボードのファームウェアをSwiftで書く
kishikawakatsumi
1
250
thread_parallel_with_free-threaded_Python_and_NumPy.pdf
riku_sakamoto
0
340
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
160
AGENTS.md Is Not Enough:Build Skills, Don't Download Them
lx_t
0
120
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
150
WebAssembly in Android Apps 〜 WASMはJNIの夢を見るか
keiji
1
110
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
300
Family mrubyの進捗
kishima
1
130
Featured
See All Featured
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.6k
4 Signs Your Business is Dying
shpigford
187
23k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
500
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
1
530
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
First, design no harm
axbom
PRO
2
1.3k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
67
58k
Optimizing for Happiness
mojombo
378
71k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.2k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
2.9k
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