2013年7月21日 星期日

[review] MVC與MVP

MVC基本職責


  • Model : 提供商業邏輯功能、知會view狀態改變
  • Controller :  接受輸入、事件,驅動model
  • View : 呈現資料,連結Controller,乃至於提供互動介面


有個有點問題的MVC用於動態網頁的設計圖

在過去application實作方式,大多使得view直接認得model,但是model只是透過observer model通知view改變,藉以解構model跟view之間的耦合

所以即使到了動態網頁,應該也不全都是透過controller傳遞scalar data而應該是傳遞model的object

借用下面的圖片說明MVC model的一種life time流程,傳統GUI元件往往把view跟controller連結再一起,所以controller由view建立,事件也由view發起


MVP

上面是在於單機application的時候,往往model會存在記憶體中相當的時間,但是到了web application時代,因為每次請求都是一個新的狀態,換句話說就是stateless,元件的功能側重的變化是

  • Model : 提供商業邏輯功能、保存資料、知會view狀態改變
  • Controller :  接受請求,驅動model,控制流程
  • View : 呈現資料,連結Controller乃至於提供互動介面


重點在web模式下發生變化的model不是持續、有狀態(stateless)的存在,也就是沒有必要去通知view更新,也辦不到。controller變得接受請求,而比較不像是事件驅動,view由html取代,與controller的連結性以及互動也變得稀薄

由於應用場景的不同,使得MVC這個架構並不是很適合,而產生了新的變形

因為是stateless,所以每次請求都類似service,controller需要分配協調的功能性變弱。這設計模式進一步想解開model/view之間的耦合,連observer pattern都想擺脫掉,另外引入了matrin folwer的IoC思維


  • View : 呈現資料以及對presenter提出請求
  • Presenter : 提供services,只有特定的介面,所以view要建立合乎presenter的介面 (IoC)
  • Model : 照舊XD,但是完全不必再去通知view

這樣的設計好或不好要看場合,由於拿掉了observer pattern,model的改變在web應用上很沒有問題,因為model是被動的,並不用及時通知前端(view)改變。所以在win form上面的設計model有時是跟presenter上是雙向溝通的,可以讓model通知presenter,進而更新view,這點在martin folwer的supervising controller上也有提到
有趣的是,這樣的想法比較接近一開始的圖,所以我說那張MVC的圖有問題XD



參考資料:
一個做得不錯的MVC投影片


Backbones.js
http://documentcloud.github.io/backbone

MVP實作參考
http://www.cnblogs.com/leoo2sk/archive/2010/01/28/mvp-in-practice-based-on-dot-net.html

2013年7月18日 星期四

[說文解字]何謂blog?何謂social networks

圖片內有來源XD


[Review] PHP Tools

壓力測試


  • ApacheBench (ab)
  • JMeter
  • Siege


記得把防火牆關閉,類似DoS的動作會因為防火牆而失敗

快取

pecl install apc
記得在php.ini內加入extension=apc.so

Profiling

XHProf,來自facebook常用的好工具

程式分析工具


  • phploc
  • phpcpd/phpmd,找出php code重複的地方,找出bad smell
  • phpcs,一種是否合乎某種規格的探測器,比方是否遵循某種命名法則、有無comment
  • phpdoc/php-apigen,文件產生器

測試


  • PHPUnit (單元測試/unit test)
  • Behat/PHPSpec (行為測試/behavior test)
  • Selenium (系統測試)

版本控制工具


  • SVN
  • GIT
  • Phing,deploy工具

MVC framework

直接參考這邊吧http://jonathanmh.com/best-php-mvc-frameworks-of-2013/

有陣子沒玩PHP了,最近review了一下,順手紀錄了一下

2013年7月14日 星期日

GRASP General Responsibility Assignment Software Patterns

這是回顧Applying UML and Patterns一書(chapter 16 or 17?)上面提到的設計原則
  • information expert
  • creator
  • high cohesion
  • low coupling
  • controller
Q. 誰該被分配某個operations?
A. information expert提示將operation交付予擁有資訊的類別,也就是賦予相對應的責任,哪個內別有資訊,便應當負起處理該資訊的任務

Q. 誰該建立某類的物件?
A. creator告訴我們擁有下列狀況的腳色或許應處理
  • B聚合(aggregate)有 A
  • B包含(contain)A
  • B record A
  • B closely use A
  • B have initialization information of A

Q. 將某個方法或者屬性分配給...
A. low coupling是個好的選擇,提升coupling儘量避免,除非他們的關聯性是必要的

Q. 如何保持複雜度在一定程度內?
A. high cohesion,適當的模組化,避免使得物件之間的互動很難理解、很難維護、很難reuse

Q. 誰該處理系統輸入事件? (metaphor)
A. 將處理訊息的責任指派給兩種概念的類別:

  • 代表整個系統或者子系統
  • 代表系統事件所屬的使用者情節

最後該說的,如同作者提到的CRC (class reponsibility collaborator cards)卡是個好工具

參考資料

2013年7月10日 星期三

Unit Test的好文章

雖然使用的是C#的程式語言,但是不懂應該不妨礙閱讀才是,只要學過一些OOP
http://www.dotblogs.com.tw/hatelove/archive/2012/11/05/learning-tdd-in-30-days-day2-unit-testing-introduction.aspx
上面連結說明了為何、如何使用unit test

看過之後,有個想法,如何對程序語言進行如unit test的動作,雖然C這種程序語言是不支援OO,但是如果導入unit test精神以及實作其技術(不是只有unittest class還包含類似mock, stub ...之類的)

2013年7月9日 星期二

OO的"沉重",DDD的反思

DDD是乎達成了相當了不起的成就,給出了一套方法論,讓programmer可以沿著物件導向開發的方式前進,一切的問題似乎是迎刃而解!?

但是本身的經歷說明了似乎還有長遠的路要走,下面記錄下我幾個不解之處

database/persistence是否屬於domain model??

這個大哉問其實再Martin Folwer的PoEAA有所解答,本書主要討論DB模組與OO模型之間轉換的問題,根據作者的講法,是的DB物件屬於domain model的一部分,同時hibernate可能也是實作了大多數PoEAA裡面的內容
不過在DDD內,並沒有詳細探討到DB模型如何融入到domain model內,倒是Jimmy Nilsson的著作談到,如果我們想把Persistence機制與OO模型完全切開,將會導致七八種很嚴重的"後遺症",然則讓OO model與Persistence機制完全分開又有其好處,不過看來現實是極難辦到

DDD的實際範例?

單單DDD一本書,實際上有太多縫隙需要填補,Jimmy Nisson的著作是個不錯的選項,然則還是有許多方面需要考慮的

DDD是否為唯一方式?是否與其他模範(paradigm)設計方式結合?

前者顯然否定,明顯來說一些嵌入式系統底層就無法享受這樣的好處,不過物件導向的原則倒是往往深入開發的過程。
其他典範如SOA、generic programming、Aspect...等等,都是一些很好的考量,我們看到compiler愈來愈強大,如何混合這些方法論或者技術層次的工具,都是一些開發時可以考量的。如Modern C++ design一書結合pattern以及generic programming的技巧就叫人拍案叫絕,但是個人認為這種技術的門檻太高,短時間內不會被廣泛採用。Aspect則是似乎可以解決Persistence以及OO model分割的問題

OO的"沉重",DDD (3)

此書最後的部分,也是最精彩跟抽象的部分,從單一專案開發跨足多專案開發

作者首先點出,一個大企業,裡面維護單一的專案是不可能的,也就是累積了或者同時會有好幾個專案在開發,也不是所有專案都使用OO或者DDD開發,也就是多種的可能性

然則使用Domain model,可以嘗試著去描述其他的部分,也就是domain model的本質上並不受限於任何程式語言風格,講求的是溝通以及理解

在整合的過程中,有三件事情是重要的
  • 一致性以及完整性 : 所有開發團隊對於相關的部分必須有一致的認知,否則會造成一些整合上不可預期的結果
  • 精煉 : 為了能夠掌握專案的目標,同時維護專案在可以理解的情況下,精煉、精簡出Core domain有其必要性
  • 大比例架構 : 所有事情不是一步登天,做為指導原則作者提倡大比例架構,如果特殊化,在軟體上可以稱為Architecture

一致性以及完整性

一張圖道盡整個一致性以及完整性維護的地圖

Bounded Context : 將想要表達的模型,有範圍的規劃起來,並且給予有意義的名字,同時確保範圍內不會受到其他模型的影響。
Continuous Integration : 分布整合、自動測試、概念整合、model整合,尤其是自動測試,是一種快速檢視Context之間有沒有問題的技術
Context Map : 強調各bounded context之間的交互作用,可以思考SOA是如何運作

由上面三個主要元素,可以知道,在畫分完畢後,主要的問題將是context之間的介面

最常見的是介面/service之間的問題,是否由相同團隊開發?是否有權利要求提供介面?是否需要完成自己轉接介面(adapter),而影響因素有溝通能力以及決定權

Shared Kernel : 共享的概念上子集,類似binary/source code等級的分享
Customer/Supplier Development Team : 上下游關係,如開發廠仰賴系統廠的功能,有分層的味道,兩邊必須要有適當的協調者
Conformist : 單純的跟隨者,例如開發廠完全無法要求系統廠提供任何支援性功能,那只有單純的跟隨
Anticorruption Layer : 透過實現特定層面(layer),團隊自行完成上游所不提供,但自己所需的功能

Open Host Service : 經過一段時間開發,整合所有開放的service
Published Language : 透過一種標準,開放service,如SOAP

兩大因素與採用模式的關係圖如下


精煉

為了能夠集中精神在主要目標,以及提供能夠處理的內容,深入理解context之後,精煉出主要的模型是必須的,但也是費力氣的

Domain Vision Statement : 願景是很簡短且重要的
Highlighted Core : 從大量的背景知識中抽出重要的部分
Segregated Core : 將核心更加模組化
Generic Subdomain : 將支持性的模型移出core domain
Cohesive Mechanism : 讓domain集中在what to do不是耗費在解釋how to do
Abstract Core : 抽象畫主要設計

其中作者點出了很多的風險

大比例原則

以architecture角度切入會顯得比較容易體會,但是architecture並不等於domain model,所以作者提供的觀點卻是更高階的


  • evolving order : 概念上的模型必須隨著模型一直演變
  • system metaphor : 適當的使用隱喻可以增加對系統的了解,比方說再architecture上說明是MVC
  • responsibility layers : 模型對象往往已職責為依歸,仔細觀察這些對象的變化頻率以及職責所在,可以適當的aggregate以及module化
  • knowledge level : 如果抽象對象之間的關係限制,無法完整描述,則應把限制這樣的知識暴露到domain model之中,作者舉例出,兩個物件,員工以及退休計畫,如果只有兩個對象,可以隨意匹配,然而某些員工只能享有某些退休計畫,所以把"員工種類的退休計畫"這個對象放入domain model來滿足
  • Pluggable component framework : 從interface以及interaction中抽出abstract core的部份,並且建立一個框架,符合介面的元件都可以被抽換


作者再某一章節給出了顯示完整性、精鍊以及大比例原則之間的互動,同時顯示了一個範例如何借助DDD所有技巧發展出一個domain model

2013年7月1日 星期一

OO的"沉重",DDD (2)

在軟體開發過程,每個iteration一般會不斷添加新的需求,導致domain model不斷的變化,而軟體工程師以及領域專家,對於domain model也會更了解,而為了避免domain model不斷膨脹到無法處理,人們會發揮抽象、精練的能力

作者提出了deep model以及supple design的設計,所謂deep model也就是更加抽象、更容易掌握的模型,而supple design則是彈性的設計,讓模型更容易擴充,兩者都可以透過refactoring達到,很可惜,這裡refactoring不是類似code的操作方式,而是概念上的不斷重新調整

Deep Model
在討論domain model上有幾個重要的概念,可以幫助程式設計師,找出更恰當的模型或者修正一些模型的問題

  • 反覆討論:確定與領域專家達成一致正確的共識,有時候領域專家會"尊重"程式設計師的設計,雖然這個設計可能跟現實不吻合,要反覆討論
  • 傾聽語言:從交談過程中,確定專家是否確定這個模型與描述一致
  • 找出矛盾:需求上是否有模型無法解釋處?
  • 不斷學習:尋找過去經驗,或者閱讀相關書籍
  • 找出implicit處:發覺應該抽出的概念,如限制、補充


在此作者提出了specification pattern,將依些限制或者補充,當成類似英文中的副詞的位置,有時這個元素必須要獨立出來,置於domain model,可以更加完整的描述整個模型

Supple Design
supple design的部分則是彈性的設計,然則會有overengineering的疑慮,導致過度的設計,然則一個最大的原則是low coupling  high cohesion,將複雜的模型用簡單的關係表示,不要過度使用抽象層面
作者也沒有完全給出一個恰如其分的設計的明確方式,更沒有檢驗的方式,不過提出了若干的pattern作為思考的方向,如下圖表示



  • Intention Revealing Interfaces:命名與操作時要描述他們的目的與效果,封裝物件的行為
  • Side-Effect-Free Functions:盡可能地將邏輯封裝在function內,如果必要回傳考慮回傳value object,有效的控制影響層面
  • Assertion:如果side-effect是implict的,大量交互作用下,結果變得無法預測,利用assertion可以減輕不可預期的效果
  • Standalone Classes:極致的low coupling就是standalone class
  • Closure of Operations:運作後回傳相同型態,可以降低依賴程度
  • Conceptual Contours:找出輪廓,避免關係太複雜,也避免介面無法解釋。設計得太粗糙則介面無法解釋模型,關係太複雜則是呈現了太多的細節。


A Declarative Style of Design
由上面幾個組合而成,則得到類似Design by Contract的效果,可以達到某些特性的限定

  • Acceptable and unacceptable input values or types, and their meanings
  • Return values or types, and their meanings
  • Error and exception condition values or types that can occur, and their meanings
  • Side effects
  • Preconditions
  • Postconditions
  • Invariants
可以更嚴格的保證行為以及其結果