2013年3月26日 星期二

單一職責原則 ( Single Responsibility Principle )

    在寫 django view 的時候,如果你是在寫列出該使用者所有文章,或是列出該使用者所有評論、活動之類的 view。 你會發係每個 view 基本上做的事情都差不多,不外乎就撈資料 -> 排列資料 -> 做分頁 - > 丟給 template 去呈現。像下面程式碼(以下程式碼都省略很多東西,所以請看 function name、call function 與 function doc 部分)



def list_view(request):
    ''' get data from model
        sort dataset
        page
        render
    '''


有人會看到既然列出資料的 view 程式碼長的都差不多。那就把那些事情包在一起,這樣其他 view 就可以重用了,達到程式碼重用的原則。

def reuse_code(request):
    ''' get data from model
        sort dataset
        page
        render
    '''

def list_view(request):
    reuse_code(request)


有一天,有個 list_view,撈完資料後,還要把使用者不想看到的東西除外,悲劇就發生了。 reuse_code 一點都沒辦法 reuse。因為他撈完資料後,就開始 sort 資料了、做分頁、 render 資料。 好吧,只好修改 reuse_code,把撈資料的部分獨立出來。像這樣


def reuse_code(request):
    ''' sort dataset
        page
        render
    '''

def get_data_view(request):
    ''' get data
        maybe do other thing.
    '''
    reuse_code(request)

    太棒了,程式碼可以重用了。你會有一段好日子過,可是好日子不會太久。 有一天,你發現你把資料打亂,而不是要排序。那你就無法用 reuse_code 了。或者是你只要取出前一百筆資料,你也無法用 reuse_code。

     問題出在哪? 問題出在 reuse_code 一次做太多事情了,他既負責流程(先 XXX,在 YYY,最後 ZZZ),又負責實作(  XXX 要怎麼做, YYY 要怎麼做, ZZZ要怎麼做)。好的程式設計架構應該區隔他們,讓每個函數負責的事情單一化。


def get_data(request):
    'get data'

def sort_data(request):
    'sort data'

def create_page(request):
    'create page'

def list_view(request):
    get_data(request)
    sort_data(request)
    create_page(request)

    像這樣, view 負責流程(先怎樣,在怎樣),而每個 function 負責實作。這樣如果 view 要做打亂資料的話,只有把 sort_data 換成 random_data。 好改,好維護,又方便重用程式碼,何樂不為? 現在 function call 的成本相對低很多了,當然如果你是在寫接近硬體的程式,像driver 、韌體、 kernel 之類的,成本也許還很高。但大多數的應用,function call 的成本相對低很多。

沒有留言:

張貼留言