http://debug-sai.blogbus.com/logs/51711788.html
asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count)
{
//傳入文件fd
struct file *file;
ssize_t ret = -EBADF;
int fput_needed;
//根據文件fd得到file
file = fget_light(fd, &fput_needed);
if (file) {
//讀出當前偏移
loff_t pos = file_pos_read(file);
//從當前偏移讀,pos返回讀取後的偏移
ret = vfs_read(file, buf, count, &pos);
//設置新偏移
file_pos_write(file, pos);
fput_light(file, fput_needed);//
}
return ret;
}
看看fget_light是怎麼根據fd得到file的
struct file *fget_light(unsigned int fd, int *fput_needed)
{
struct file *file;
struct files_struct *files = current->files;
*fput_needed = 0;
if (likely((atomic_read(&files->count) == 1))) {
//若已經打開了
file = fcheck_files(files, fd);
} else {
//若沒有打開,加鎖
rcu_read_lock();
file = fcheck_files(files, fd);
if (file) {
if (atomic_long_inc_not_zero(&file->f_count))
*fput_needed = 1;
else
/* Didn't get the reference, someone's freed */
file = NULL;
}
rcu_read_unlock();
}
return file;
fput_light的流程如下,具體見源代碼:
fput_light->fput(當所有釋放完時還要調用__fput)
接著看 vfs_read:
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
ssize_t ret;
//下面都是一系列驗證
if (!(file->f_mode & FMODE_READ))
return -EBADF;
if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
return -EINVAL;
if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
return -EFAULT;
ret = rw_verify_area(READ, file, pos, count);
if (ret >= 0) {
count = ret;
if (file->f_op->read)
//一般都是到這裡調用vfs的read
ret = file->f_op->read(file, buf, count, pos);
else
ret = do_sync_read(file, buf, count, pos);
if (ret > 0) {
fsnotify_access(file->f_path.dentry);
add_rchar(current, ret);
}
inc_syscr(current);
}
return ret;
}
跟著就是vfs設置的read函數了,對於ext2來說是
const struct file_operations ext2_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.unlocked_ioctl = ext2_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ext2_compat_ioctl,
#endif
.mmap = generic_file_mmap,
.open = generic_file_open,
.release = ext2_release_file,
.fsync = ext2_sync_file,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
所以是do_sync_read:
ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
{
struct iovec iov = { .iov_base = buf, .iov_len = len };
struct kiocb kiocb;
ssize_t ret;
//初始化kiocb
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos;
kiocb.ki_left = len;
for (;;) {
//其實就是變了個參數傳到generic_file_aio_read中。。。具體分析就先到這了
ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
if (ret != -EIOCBRETRY)
break;
wait_on_retry_sync_kiocb(&kiocb);
}
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
return ret;
}
2013年8月11日 星期日
2013年8月9日 星期五
[review] Brownfield Application Development in .NET
說在前頭,這是一本好書,還有我不懂C#, .NET XD
簡而言之,作者相信,好的軟體流程跟設計是一切的根本,如果專案失控,大致上是這兩方面出問題,所以一書分成兩個部分,第一部分先談到brownfield application的定義,跟著提出軟體流程的工具,比方說VCS、Testing、Defect...等等,如何使用,第二部分則是設計模式跟原則,基本上遵循design pattern的兩句話,low coupling high cohesion & design for interface。
衍生出來的就很多,比方說IoC、DI...,書中主要反應在兩種設計方式上,一個是MVP,另外一個是Anticorruption layer
Anticorruption layer
因應第三方元件或者其他需求,在每一層可以考慮加入一個layer,發揮類似seam的作用,讓上下層依賴這個介面,也就是Robert C. Martin所謂的
High-level modules should not depend upon low-level modules. Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.
每一層可以獨立作業,也不會類似過去TCP/IP的設計方式,每一層依賴於下一層,每一層都可以獨立發展
效果類似於下圖
圖片中綠色的區塊相當等於seam的部分SpellChecker跟SpellCheckDictionary可以分開獨立發展,中間接合的部分,由ISpellCheckDictionary承擔,有MVP的味道
簡而言之,作者相信,好的軟體流程跟設計是一切的根本,如果專案失控,大致上是這兩方面出問題,所以一書分成兩個部分,第一部分先談到brownfield application的定義,跟著提出軟體流程的工具,比方說VCS、Testing、Defect...等等,如何使用,第二部分則是設計模式跟原則,基本上遵循design pattern的兩句話,low coupling high cohesion & design for interface。
衍生出來的就很多,比方說IoC、DI...,書中主要反應在兩種設計方式上,一個是MVP,另外一個是Anticorruption layer
Anticorruption layer
因應第三方元件或者其他需求,在每一層可以考慮加入一個layer,發揮類似seam的作用,讓上下層依賴這個介面,也就是Robert C. Martin所謂的
High-level modules should not depend upon low-level modules. Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.
每一層可以獨立作業,也不會類似過去TCP/IP的設計方式,每一層依賴於下一層,每一層都可以獨立發展
效果類似於下圖
圖片中綠色的區塊相當等於seam的部分SpellChecker跟SpellCheckDictionary可以分開獨立發展,中間接合的部分,由ISpellCheckDictionary承擔,有MVP的味道
2013年8月4日 星期日
javascript loading的考量
javascript loading有些必須考量的點,比方載入方式、相依性、模組化、最佳化
2. 使用document.write方式動態載入
3. 自行產生DOM元素加入
4. 使用AJAX動態取得
現在web browser通常使用aysnchronous載入,最佳化性能,但是有時必須考慮相依性
參考資料:
https://developers.google.com/closure/compiler/?hl=zh-TW
http://josephj.com/entry.php?id=349
http://www.jb51.net/article/17992.htm
http://ithelp.ithome.com.tw/question/10120521?tag=rss.qu
http://tc.itkee.com/developer/detail-1a9a.html
http://www.puritys.me/docs-blog/article-160
方式
1. 直接使用script tag的src屬性2. 使用document.write方式動態載入
3. 自行產生DOM元素加入
4. 使用AJAX動態取得
現在web browser通常使用aysnchronous載入,最佳化性能,但是有時必須考慮相依性
相依性
javascript loading相依性上有RequireJS來處理,一來可以解決相依性,二來可以只載入必要的元素即可模組化
而引入的javascript通常可以視為一個模組,一個好的模組必須符合一些規範,如AMD,而CommonJS正是這樣的概念下的RIA framework最佳化
而javascript載入有時取決於script tag的位置,變數名稱以及檔案形式。好比將tag至於文件尾端,讓DOM Tree儘快生成,產生頁面,但是副作用是有時script產生的動態元素會比較慢呈現在網頁上。為了讓javascript parser比較快讀取產生,使用如google closure compiler,縮短變數名稱等等動作,可以讓javascript產生較好的效能,但是會犧牲程式的可讀性參考資料:
https://developers.google.com/closure/compiler/?hl=zh-TW
http://josephj.com/entry.php?id=349
http://www.jb51.net/article/17992.htm
http://ithelp.ithome.com.tw/question/10120521?tag=rss.qu
http://tc.itkee.com/developer/detail-1a9a.html
http://www.puritys.me/docs-blog/article-160
2013年8月1日 星期四
[review] MVP
之前在網路上搜尋MVP的時候,無意看到有人說MVC更適合web application這種stateless的開發,非常違反我直覺地描述,最近終於發現可能得出處,是一本書
Brownfield Application Development in .NET,中文翻譯:軟體構築美學
先說違反直覺的部分,首先MVC提出非常早,遠早於現在流行的web application,也就是說MVC一開始是為了application設計才對,以這種觀點,application大多屬於有狀態的(state),很少是stateless
作者有幾點小小的誤會,首先MVC架構定義跟傳統不大一樣,可以參考POSA一書對MVC架構的描述,MVP不是Martin Folwer提出來的,首先是由IBM於1997年左右提出的,Martin Folwer的MVP算是IBM的改良版本,這種誤解有點類似Martin Folwer提出了refactoring的概念是一樣的,不過Martin Folwer是一個總結並且發揚光大的人是肯定的,非原本名詞的提出者,一點都不損及Martin Folwer的地位
撇開這個不講,書中對各種模型的描述倒是很清楚,如Passive View、Supervising Controller、MVC、MVP
為了觀察web application,先考慮過去MVC是由誰驅動?大多是由應用程式建立了一堆view之後,再由view引發事件驅動controller,可是在web appliction,卻是由網頁直接接觸controller,然後再產生新的view(網頁)
因為stateless以及web流程的特性,controller變成了進入點,再加上route的概念盛行,controller工作變成了,如何引導流程,且非由view創立出來的,所以整體的角色改變了
再者MVC本身有個小小的缺點,view本身是認知model的存在(耦合性),這有一點點暴露風險的部分是,程式設計師會直接透過view去操作model,而非controller,此外view往往為了model必須要修改,無法獨力發展
MVP有效的解決這問題,首先view直接獨立發展,畫面更新等等事情交由presenter去考慮,model本身從前就已經很獨立了,現在更加地不用透過類似observer patter去通知view,耦合更少。在view與model都獨立的狀況下,必須有角色負責媒合兩者,那個就是presenter,而presenter必須利用IoC的概念,引入兩者view跟model(有可能有很多view與很多model instances),作為媒介
可是這時候,一些事件的傳遞要如何作用?在web application上面,這件事情不是很嚴重,因為server直接扮演了controller以及route腳色,如同第一個MVC圖片一樣,只是現在將MVC中的MV改成了MVP,但是在應用程式上呢?所以才有上面的application controller存在。
這裡可能會冒出的疑問是,那麼model跟view之間的耦合性不見了,那麼如何更新view?由presenter,但是presenter也無法知道model有沒有更新阿!?Martin Folwer告訴我們,如果要達到主動更新只好把類似observer pattern再放到model跟presenter身上,耦合性又回來了XD天下沒有白吃的午餐,不過透過MVP,讓view與model可以獨立發展,大大提高view的resue了
Brownfield Application Development in .NET,中文翻譯:軟體構築美學
先說違反直覺的部分,首先MVC提出非常早,遠早於現在流行的web application,也就是說MVC一開始是為了application設計才對,以這種觀點,application大多屬於有狀態的(state),很少是stateless
作者有幾點小小的誤會,首先MVC架構定義跟傳統不大一樣,可以參考POSA一書對MVC架構的描述,MVP不是Martin Folwer提出來的,首先是由IBM於1997年左右提出的,Martin Folwer的MVP算是IBM的改良版本,這種誤解有點類似Martin Folwer提出了refactoring的概念是一樣的,不過Martin Folwer是一個總結並且發揚光大的人是肯定的,非原本名詞的提出者,一點都不損及Martin Folwer的地位
撇開這個不講,書中對各種模型的描述倒是很清楚,如Passive View、Supervising Controller、MVC、MVP
為了觀察web application,先考慮過去MVC是由誰驅動?大多是由應用程式建立了一堆view之後,再由view引發事件驅動controller,可是在web appliction,卻是由網頁直接接觸controller,然後再產生新的view(網頁)
因為stateless以及web流程的特性,controller變成了進入點,再加上route的概念盛行,controller工作變成了,如何引導流程,且非由view創立出來的,所以整體的角色改變了
再者MVC本身有個小小的缺點,view本身是認知model的存在(耦合性),這有一點點暴露風險的部分是,程式設計師會直接透過view去操作model,而非controller,此外view往往為了model必須要修改,無法獨力發展
MVP有效的解決這問題,首先view直接獨立發展,畫面更新等等事情交由presenter去考慮,model本身從前就已經很獨立了,現在更加地不用透過類似observer patter去通知view,耦合更少。在view與model都獨立的狀況下,必須有角色負責媒合兩者,那個就是presenter,而presenter必須利用IoC的概念,引入兩者view跟model(有可能有很多view與很多model instances),作為媒介
可是這時候,一些事件的傳遞要如何作用?在web application上面,這件事情不是很嚴重,因為server直接扮演了controller以及route腳色,如同第一個MVC圖片一樣,只是現在將MVC中的MV改成了MVP,但是在應用程式上呢?所以才有上面的application controller存在。
這裡可能會冒出的疑問是,那麼model跟view之間的耦合性不見了,那麼如何更新view?由presenter,但是presenter也無法知道model有沒有更新阿!?Martin Folwer告訴我們,如果要達到主動更新只好把類似observer pattern再放到model跟presenter身上,耦合性又回來了XD天下沒有白吃的午餐,不過透過MVP,讓view與model可以獨立發展,大大提高view的resue了
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日 星期四
[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 ...之類的)
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可以沿著物件導向開發的方式前進,一切的問題似乎是迎刃而解!?
但是本身的經歷說明了似乎還有長遠的路要走,下面記錄下我幾個不解之處
不過在DDD內,並沒有詳細探討到DB模型如何融入到domain model內,倒是Jimmy Nilsson的著作談到,如果我們想把Persistence機制與OO模型完全切開,將會導致七八種很嚴重的"後遺症",然則讓OO model與Persistence機制完全分開又有其好處,不過看來現實是極難辦到
其他典範如SOA、generic programming、Aspect...等等,都是一些很好的考量,我們看到compiler愈來愈強大,如何混合這些方法論或者技術層次的工具,都是一些開發時可以考量的。如Modern C++ design一書結合pattern以及generic programming的技巧就叫人拍案叫絕,但是個人認為這種技術的門檻太高,短時間內不會被廣泛採用。Aspect則是似乎可以解決Persistence以及OO model分割的問題
但是本身的經歷說明了似乎還有長遠的路要走,下面記錄下我幾個不解之處
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)
此書最後的部分,也是最精彩跟抽象的部分,從單一專案開發跨足多專案開發
作者再某一章節給出了顯示完整性、精鍊以及大比例原則之間的互動,同時顯示了一個範例如何借助DDD所有技巧發展出一個domain model
作者首先點出,一個大企業,裡面維護單一的專案是不可能的,也就是累積了或者同時會有好幾個專案在開發,也不是所有專案都使用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上有幾個重要的概念,可以幫助程式設計師,找出更恰當的模型或者修正一些模型的問題
在此作者提出了specification pattern,將依些限制或者補充,當成類似英文中的副詞的位置,有時這個元素必須要獨立出來,置於domain model,可以更加完整的描述整個模型
Supple Design
supple design的部分則是彈性的設計,然則會有overengineering的疑慮,導致過度的設計,然則一個最大的原則是low coupling high cohesion,將複雜的模型用簡單的關係表示,不要過度使用抽象層面
作者也沒有完全給出一個恰如其分的設計的明確方式,更沒有檢驗的方式,不過提出了若干的pattern作為思考的方向,如下圖表示
A Declarative Style of Design
由上面幾個組合而成,則得到類似Design by Contract的效果,可以達到某些特性的限定
作者提出了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
可以更嚴格的保證行為以及其結果
2013年6月29日 星期六
OO的"沉重",DDD (1)
Domain Driven Design提示了我許多以前沒看過的議題,如何讓設計者更加專心地在OO上面
Domain model是一種Ubiquitous lanuage
為何不如XP之類的agile process採用user story之類的技巧呢?主要的問題在於各個user story以及design存在於設計師的心中,是一種隱性的資料(implicit data),其次agile process,往往產出的主要成果是code,code是一種完美的實現(implemetation)的呈現,然則是太細節,如果將專案的整個class diagram畫在黑板上鐵定很壯觀,但是恐怕解釋要花上很久
而如同agile process一樣,必須發展適當的、共通的語言,將設計精簡的呈現出來,且DDD和agile process一樣相信,feedback是很重要的,設計過程必須和使用者溝通,也就是"語言"主要的用途
如何從問題/需求過渡到設計,DDD的方式採用了類似DB Table design(這是一個很不好的比喻,但是退化/極簡的domain model幾乎就是這種模式),跟著利用design pattern作為指引,可以簡單地使用下面的圖形作為依據
設計工作主要圍繞著service、entity、value object之間的設計
而entity以及value object中間往往有關係,在設計上,希望關係(關係在設計圖上用連線表示)愈簡單愈好,避免太過複雜的關係,簡化關係的方式有三
另外一種"打包"關係的方式就是使用aggregation,將物件打包成一個entity,所有內部資料必須透過root處理,且參考到的物件,往往只是value object,也就是並不會影響到實際物件內部物件的狀態
同樣的,如果需要生成狀態的抽象畫,可以使用factory pattern。而repository pattern則適用於查詢相似物件的應用或者封裝travel/filter的行為,比方說,從persistence裝置找到所有大於65歲的老年人口,如果要從某個根物件訪問到所有符合條件的物件太過費時、複雜且沒效率。
DDD有兩個特色,全都形而上,幾乎不涉及persistence,也不涉及class定義等等的部分(GoF多少有class定義)。DDD提示我們如何專注在OOAD上面,而非過去的設計模式(procedure or others)
這裡有些anti-pattern,可供參考,是否是使用舊的方式在設計
經過這些基本考量之後,跟著在每個iteration,如何繼續改善domain model,是一個重要的工作,而且沒有固定的方法
Domain model是一種Ubiquitous lanuage
- 現實以及模型做綁定,這是很簡單的規則,但是往往愈到專案後期,分析的模型愈是和實際的程式碼相差愈大
- Domain Model不是單純的圖形,他是一種語言,也就是包含了上下文(context)
- Domain Model因為有語言的特色,大家需要看得懂,聽得懂
- Domain Model必須不斷的精練,也就是隨著專案成長以及精簡
為何不如XP之類的agile process採用user story之類的技巧呢?主要的問題在於各個user story以及design存在於設計師的心中,是一種隱性的資料(implicit data),其次agile process,往往產出的主要成果是code,code是一種完美的實現(implemetation)的呈現,然則是太細節,如果將專案的整個class diagram畫在黑板上鐵定很壯觀,但是恐怕解釋要花上很久
而如同agile process一樣,必須發展適當的、共通的語言,將設計精簡的呈現出來,且DDD和agile process一樣相信,feedback是很重要的,設計過程必須和使用者溝通,也就是"語言"主要的用途
如何從問題/需求過渡到設計,DDD的方式採用了類似DB Table design(這是一個很不好的比喻,但是退化/極簡的domain model幾乎就是這種模式),跟著利用design pattern作為指引,可以簡單地使用下面的圖形作為依據
設計工作主要圍繞著service、entity、value object之間的設計
- entity含有唯一ID,且生命週期間狀態的轉換是有意義的,如身分證
- value object則是臨時的狀態,通常是依附於entity上面
- service則是一種類似於基礎建設的存在,往往處於領域的邊界,如DNS service
而entity以及value object中間往往有關係,在設計上,希望關係(關係在設計圖上用連線表示)愈簡單愈好,避免太過複雜的關係,簡化關係的方式有三
- 限定travel方向
- 限定關聯方式
- 減少關聯
同樣的,如果需要生成狀態的抽象畫,可以使用factory pattern。而repository pattern則適用於查詢相似物件的應用或者封裝travel/filter的行為,比方說,從persistence裝置找到所有大於65歲的老年人口,如果要從某個根物件訪問到所有符合條件的物件太過費時、複雜且沒效率。
DDD有兩個特色,全都形而上,幾乎不涉及persistence,也不涉及class定義等等的部分(GoF多少有class定義)。DDD提示我們如何專注在OOAD上面,而非過去的設計模式(procedure or others)
這裡有些anti-pattern,可供參考,是否是使用舊的方式在設計
- 每個entity就是對應一個table或者一個record
- 關係非常複雜,很多關係是雙向的
- 所有物件的persistence是由一個巨大的facade對應到DB或者檔案
經過這些基本考量之後,跟著在每個iteration,如何繼續改善domain model,是一個重要的工作,而且沒有固定的方法
OO的"沉重",architecture design(架構設計)
初步建立
從需求捕捉=>分析=>設計=>code,由OOAD到OOP是一件不簡單的工作,從UP來說,可能的流程是這樣的
中間過程
建構架構
從需求捕捉=>分析=>設計=>code,由OOAD到OOP是一件不簡單的工作,從UP來說,可能的流程是這樣的
Use cases=>analysis model=>design model=>code
如果簡單的說,就是找出需求,分析的時候分離出名詞跟動詞,將其組合成物件,跟著抽象化倒出analysis model,借用design pattern設計出模型,最後寫出程式碼
中間過程
似乎很簡單,但是中間很多空隙(gap)需要填充,比方說UP推崇architecture centric的思維,那麼如何找出architecture?這是一個很困難的工作
為了設計architecture,UP擴展了許多東西,首先他們在use cases內部添加了一些constraints,表達non-functional features,比方fault tolerance、performance ...,這些非功能性的限制,跟著引入了controller、boundary object以及entity組成的collaboration diagram
利用sub system interface做切割,填補design以及requirement之間的縫隙,並且完成其中的對應(tractability在CMMI很重要!)
建構架構
UP中architecture centric的設計方式有賴經驗,而且要take care的重點很多,很難一概而論,同時要考慮user centric、functional features跟non-functional features,導致作法多樣,同時為了抽象表示的不足,在UP才引入collaboration diagram
在設計architecture的時候可以考慮Matrin Folwer的建議,使用domain model,可以使用DDD (domain driven design)模式,DDD一口氣跳過分析方式,直接由需求到設計,而DDD面臨的兩個議題是,模型的描述語言以及分析的方式
在DDD的部分,使用domain model是很好的選擇,跟UP的collaboration diagram很像,然則也不是那麼容易。主要一個議題是,如何符合iterative建構?如果要辨識出所有的需求再來考慮architecture,整體就變得類似waterfall的設計方式
模型的描述語言DDD使用類似class diagram的模型,並且加上類似use case的補充來描述,客戶專家以及程式設計師,必須懂得同樣的terms,DDD模型大多時候不考慮operations,連attributes也很少紀錄,畢竟是一種抽象思考。
另外一個議題是分析的方式,DDD利用design pattern填補分析方式的不足,DDD相信大家都可經由消化知識,抽象畫原本的議題,進而達成共識(領域專家未必能接受這種語言),其次這裡的design pattern也與GoF不大一樣,主要注重抽象的層級
另外一種architecture的設計方式類似DDD,首先確立業務目標(白雲,參考writin effective use case 一書),接著確立範圍以及特色(風箏跟海平面),同時利用類似use case的上下文(context)來分割出architecture的輪廓,本質上跟DDD很類似,但是只是比較方法論去形塑domain model
不管DDD或者是使用UP的cooperation diagram,重點必須找出重要的(考慮各種non-functional feature)、主要的(risk)、使用者最關心的(user centric),來做為architecture model,如果單純依照UP提示的,找出涵蓋整個系統,一寸深的architecture,我想只有非常資深的設計師才能做到,且有太多不必要的考量因素
還缺了甚麼?
architecture相當程度是為了演繹一些系統重要的部分,形成重要的骨幹,然則與DDD/Domain model有點不大一致,Domain model主要是要表達整體的概念,而DDD則是以Domain model為依歸衍生設計
可以說architecture是Domain model的主要部分,用以檢驗是否滿足各種需求(functional and non-functional)
還缺了甚麼?
architecture相當程度是為了演繹一些系統重要的部分,形成重要的骨幹,然則與DDD/Domain model有點不大一致,Domain model主要是要表達整體的概念,而DDD則是以Domain model為依歸衍生設計
可以說architecture是Domain model的主要部分,用以檢驗是否滿足各種需求(functional and non-functional)
2013年6月26日 星期三
CMMI簡介(1)
說到CMMI,一般就是拜讀CMMI: Guidelines for process Integration and Product Imporovement這一本書
- CMMI由眾多的process組成,通過特定process之後可以達到某個Level,但是主要又以objective為主
- 每個process分成許多的objective,如果只跟該process有關的為specific goal (SG),跟整個level有關的objective列為generic goal (GG)
- 每個SG或者GG有許多practice ,分別是SP跟GP,往往跟產出的work product有關,也就是要有相關的描述
- 然則CMMI告訴大家What to do,但是沒有告訴大家How to do,所以以軟體來說,軟體工程/軟體流程/PMP是很好具體實踐的手法
- CMMI涉及組織流程的以及process的推行,這部分倒是軟體工程較少著墨,軟體流程幾乎從缺的地方
軟體測試...筆記(1)
因為教科書上面已經寫了很多,撇開測試的定義以及目的不談,單以軟體流程來說(也就是不涉及組織行為),最容易一窺全貌的是最著名的V-model或者W-model
但是從W-model來說,由於太過抽象,一般在requirement test跟functional test變得很模糊
比方說,requirement test可以執行幾樣工作的檢查
- Visible ?
- Clear? (unambiguous)
- Complete?
- Consistent? (conflicting requirements must be prioritized)
- Reasonable? (achievable)
- Measurable? (quantifiable)
- Modifiable? (will it change or is it stable?)
- Traceable? (the source is known)
- Dependent requirements identified?
- Testable? (given current environment, resources, skills)
或許可以使用specification by example的作法,再來檢驗這件事情會比較容易,也比較全面,以specification by example為骨幹,檢驗這幾個因素為分支,這樣就顯得較為明顯。
至於其他V model內建議的unit test, integrated test, system test, acceptance test比較工程化,也比較容易理解
以工程化的測試來說
依照測試特性可以分成
- 白箱測試
- 灰箱測試
- 黑箱測試
依照開發過程可以分成
- unit test
- integrated test
- system test
- acceptance test
- regression test
依照需求分類可以分成
- smoke test
- sanity test
- benchmark test
依照性質分類可以分成
- functional test
- equivalance class test
- boundary test
- random test
- state transition test
- nonfunctional test
- install/uninstall test
- usability test
- negative test
- recovery test
- security test
- compatibility test
- performance test
- stress test/load test
- volume test
- ad hoc test
在CMMI Level 3中可以對應到Verfication and Validation (V&V) KPA這個項目
Verfication : Are we building the thing right?
Validation : Are we building the right thing?
主要任務是
- 可追蹤性分析
- 評估
- 介面分析
- 關鍵性分析
- 測試
- 危害性分析
- 風險分析
- 其他
2013年5月27日 星期一
hadoop入門(1)
安裝jdk
add-apt-repository "deb http://archive.ubuntu.com/ubuntu hardy main multiverse"
add-apt-repository "deb http://archive.ubuntu.com/ubuntu hardy-updates main multiverse"
add-apt-repository "deb http://archive.canonical.com/ lucid partner"
apt-get update
apt-get install sun-java6-jdk
設定環境變數
export JAVA_HOME=
export CLASSPATH=
export PATH=
安裝ssh server
apt-get install ssh
設定key
ssh-key-gen -t dsa -P '' -f ~/.ssh
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
下載hadoop並且解開
我用的是1.2
找到WordCount範例,網路上很多,已經是hadoop基本的hello world了
編譯方式javac WordCount.java -classpath ~/hadoop-1.2.0/hadoop-core-1.2.0.jar
打包jar -cvf wordcount.jar -C wordcount/ ./
準備input檔案
echo "hello world bye world" >file01
echo "hello hadoop bye hadoop" >file02
~/hadoop/bin/hadoop dfs -mkdir input
~/hadoop/bin/hadoop dfs -put ~/file0* input
執行
~/hadoop/binhadoop wordcount.jar WordCount input output
=============
hadoop基本有兩部分dfs以及map-reducer
因為要分散式計算以及顧及到容錯,所以採取dfs
跟著map將輸入分散,然後再由reduce整合,map分散的時候輸入一組key1,value1,map運算完畢則是輸出另一組key2,value2,reduce則是根據key 2, value 2做資料整合,接著輸出key3, value3
從word count來說,key1可能是jab id或者hadoop產生的key,value則為一串文字,跟著將字串分解成單字,寫出的(key2, value2)可能是(hello,1),接著reducer收到後會把這些數值加總起來,跟著輸出(key3, value3)可能為(hello, 2)
add-apt-repository "deb http://archive.ubuntu.com/ubuntu hardy main multiverse"
add-apt-repository "deb http://archive.ubuntu.com/ubuntu hardy-updates main multiverse"
add-apt-repository "deb http://archive.canonical.com/ lucid partner"
apt-get update
apt-get install sun-java6-jdk
設定環境變數
export JAVA_HOME=
export CLASSPATH=
export PATH=
安裝ssh server
apt-get install ssh
設定key
ssh-key-gen -t dsa -P '' -f ~/.ssh
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
下載hadoop並且解開
我用的是1.2
找到WordCount範例,網路上很多,已經是hadoop基本的hello world了
編譯方式javac WordCount.java -classpath ~/hadoop-1.2.0/hadoop-core-1.2.0.jar
打包jar -cvf wordcount.jar -C wordcount/ ./
準備input檔案
echo "hello world bye world" >file01
echo "hello hadoop bye hadoop" >file02
~/hadoop/bin/hadoop dfs -mkdir input
~/hadoop/bin/hadoop dfs -put ~/file0* input
執行
~/hadoop/binhadoop wordcount.jar WordCount input output
=============
hadoop基本有兩部分dfs以及map-reducer
因為要分散式計算以及顧及到容錯,所以採取dfs
跟著map將輸入分散,然後再由reduce整合,map分散的時候輸入一組key1,value1,map運算完畢則是輸出另一組key2,value2,reduce則是根據key 2, value 2做資料整合,接著輸出key3, value3
從word count來說,key1可能是jab id或者hadoop產生的key,value則為一串文字,跟著將字串分解成單字,寫出的(key2, value2)可能是(hello,1),接著reducer收到後會把這些數值加總起來,跟著輸出(key3, value3)可能為(hello, 2)
2013年4月17日 星期三
system call open()
今天review linux character driver的時候,發現往往定義的file_operations的.open成員,參數擁有file以及inode參數,可是這個參數哪邊來的?
其實會對open()有好奇,主要也是之前一直在trace linux kernel source內一些socket的東西,socket本身由sockfs支援,不使用open()而用socket()來開啟inode,所以想說兩者的區別是?
kernel內用 inode 結構體用來表示data。因此,它和 file structure 用來表示一個打開了的fd並不相同。對於一個inde,可能會有多個 file structure 對應著多個已打開的多個fd,但是這都只能指向同一個 inode 結構。
回頭看open(),大多數的system call使用interrupt 0x80,所以很快地追蹤到sys_open()是理所當然的入口
簡化整個call stack為sys_open()=>filp_open()=>dentry_open()=>dentry_open()
在呼叫register_chrdev()的時候將有覆寫的file_operations賦予device
底下是一些重要的工作,完整的source code就不列了
sys_open() : 配置fd
filp_open() : 依賴路徑取得nameidata結構,跟著呼叫dentry_open()取回file instance
dentry_open() : 配置file instance,nameidata結構內包含了inode instance,此時將一些必要資料由inode拷貝到file instance,f->f_op = fops_get(inode->i_fop);,此時f->f_op->open(inode,f)就是當時register_chrdev()所註冊的file_operations。
參考資料:
http://hi.baidu.com/potyzhang/item/ae9993a919e86f17a8cfb793
http://hi.baidu.com/heiyebujianwo/item/fa7fe543d99b73ab61d7b9cb
其實會對open()有好奇,主要也是之前一直在trace linux kernel source內一些socket的東西,socket本身由sockfs支援,不使用open()而用socket()來開啟inode,所以想說兩者的區別是?
kernel內用 inode 結構體用來表示data。因此,它和 file structure 用來表示一個打開了的fd並不相同。對於一個inde,可能會有多個 file structure 對應著多個已打開的多個fd,但是這都只能指向同一個 inode 結構。
回頭看open(),大多數的system call使用interrupt 0x80,所以很快地追蹤到sys_open()是理所當然的入口
簡化整個call stack為sys_open()=>filp_open()=>dentry_open()=>dentry_open()
在呼叫register_chrdev()的時候將有覆寫的file_operations賦予device
底下是一些重要的工作,完整的source code就不列了
sys_open() : 配置fd
filp_open() : 依賴路徑取得nameidata結構,跟著呼叫dentry_open()取回file instance
dentry_open() : 配置file instance,nameidata結構內包含了inode instance,此時將一些必要資料由inode拷貝到file instance,f->f_op = fops_get(inode->i_fop);,此時f->f_op->open(inode,f)就是當時register_chrdev()所註冊的file_operations。
參考資料:
http://hi.baidu.com/potyzhang/item/ae9993a919e86f17a8cfb793
http://hi.baidu.com/heiyebujianwo/item/fa7fe543d99b73ab61d7b9cb
2013年4月10日 星期三
2013年3月30日 星期六
UP與Agile process的比較
以個人經驗提出兩者的差異
- agile使用user story捕捉需求,UP使用use case(文件,不是diagram)
- agile工程師往往一人身兼多職,從design architecture、designer、programmer
- UP並沒有強調是否一人身兼多職,但是往往將腳色獨立出來
- agile很強調Test,不是只有Unit Test還包含ATDD、BTDD
- agile認為文件必須要很精簡,UP則是比較鉅細靡遺
- agile很重視客戶合作,強調客戶需要配合軟體開發
- agile將"關係"維護在人之間,UP則是將關係落實到文件內
- Iterative方式
- 重視User Feedback
- 重視需求文件
- Risk driven
- 重視Architecture
- 重視business goal
agile實施起來未必比UP容易,agile裡的programmer往往一人身兼多種腳色,因此agile的programmer往往能力需要比較強,這也是為何早期XP強調pair programming的方式,一方面可以有feedback,另外一方面可以帶起新手
如果今天團隊內有人離職,UP因為將所有內容都記錄在文件上,理論上只要詳讀文件就可以理解,但是agile則是將一些隱含的關係放在人之間,一個programmer離職,恐怕新手只有user story以及code/test code可以讀取,有沒有design...等等的文件,則是看當時狀況
agile將某些資訊放到人之間,有個好處,由於資訊是共享的所以可以減少誤解,同時人在資訊上的更新,某種程度是比文件來的有彈性以及快速
agile最核心的難度恐怕在於改變人,因為過去客戶往往不瞭解他們的需求,同時也不了解軟體開發的一些資訊,客戶認為軟體專案如同販賣機一樣,只要錢投下去,軟體就會跑出來,agile正嘗試改變這一點
最後補上一個軟體工程的V-mode,由於agile很重視test,同時如果理解的話,應該就知道CMMI的 V&V在要求啥了。也就是只要了解軟體工程,自然可以滿足CMMI的Level 2, 3(除了4個跟organization相關的GG之外)
訂閱:
文章 (Atom)




.gif)









