【翻譯】塑形成功框架的哲學

來源:Philosophies that Shaped Successful Frameworksjavascript

在過去的十年裏咱們看到了許多軟件框架的出現,像 SpringRuby on Rails 已是很是成功的框架了,掌握它們就意味着打開多扇就業機會的大門了。然而,對於每個框架的成功,背後的大多數開發人員都不被人關注。2008年1月1日維基百科 列出了67個 Web 框架。然而今天,超過三分之二的消失在列表中或在三年內沒有更新。做爲 Yii 框架的創造者,我花了不少時間調查各類框架和理解爲何有些成功,有些失敗了。我將描述我發現塑形成功框架的一些哲學。php

爲何框架?

創建一個成功的框架,重要的是要了解什麼是框架,開發人員爲何須要它們。html

Douglas C. Schmidt 等人 認爲框架做爲一個集成的軟件構件(如類、對象和組件)集合,爲相關應用程序提供一個可重用的體系結構。根據這必定義,
框架應該是一個已完工的應用骨架組成可重用和可定製的組件。開發人員將擴展並定製一個框架經過提供他們的應用程序和領域特定邏輯來造成一個完整的應用程序。java

一個框架典型的特徵就是所謂的控制反轉(inversion of control)。框架一般扮演着組織主程序的角色和調用應用程序代碼。這裏是反過來的控制流——它調用我而不是我調用框架。下圖說明了框架之間的關係,函數庫,和應用程序。注意框架一般提供現成的功能的庫,以幫助開發人員構建應用程序更快。python

圖片描述

開發人員使用框架最重要的緣由是框架如何提升生產力和幫助提升代碼質量。例如,現代的框架(例如,django),常常提供代碼生成工具或樣板幫助當即啓動新項目。此外,精心設計的框架內嵌安全保護措施,幫助預防開發人員犯典型的安全漏洞。web

企業使用框架,還有一個額外的好處是,它能夠應用在整個企業,幫助執行標準。框架提供了記錄模式,詳細的設計和實現的工具用於在全部應用程序之間提供一個一致的結構。例如,在 Capital One (譯者注:薛強所在的公司) 咱們開發一個 「Chassis」的框架做爲一個集成的基礎,統一了許多廠商和顧客公司內部開發應用程序的 API。spring

固然,並非全部的開發人員喜歡使用框架。一些一致的抱怨包括陡峭的學習曲線,框架耦合性比較高,性能較低,等等。今天,在這篇文章中我將爲你解釋現代框架如何的解決這些問題,讓大多數的這些抱怨再也不適用。sql

<!--more-->數據庫

哲學

像任何一個產品同樣,一個框架的成功取決於許多因素,包括其背後的思想,代碼質量、文檔,周圍社區,營銷,支持,等等。在我看來,特別重要的一項是考慮當一個框架被設計和開發的哲學。express

很久之前 Python 開發者 Tim Peters 開發 Python 時發表了被稱爲 Python 之禪 的二十格言設計原則。『優美勝於醜陋,明瞭勝於晦澀,簡潔勝於複雜……』他們鼓舞了許多相似的編程語言之禪(similar programming language zens),我發現這些格言是適用於框架設計的。根據個人框架開發經驗,我特此冷凝和總結我認爲任何成功的框架最重要的哲學。

  • 越簡單越好

  • 總體設計是最糟糕的

  • 一致性

  • 明瞭勝於晦澀

  • 約定大於配置

越簡單越好

讓開發人員轉換一個新的框架歷來都不是一件容易的事。然而,當開發人員選用框架,會做爲重點依靠它來投資當前和將來的項目。此外,不想使用類庫 - 開發人員能夠學習一個 API 實現它 - 學習框架要求開發人員在投入實際使用以前要充分理解框架規則。所以,重要的是要確保簡單的設計一個框架,使它更容易、有趣,並且容易去學習,接受和利用。

爲了實現簡單,一個框架應該強制執行必定數量的限制規則;同時,這些規則應以統一的方式設計和有良好的文檔記錄。框架執行更多的規則,陡峭的學習曲線,讓開發人員很難接受。當規則是一致的,開發人員能夠更快學習它們。沒有文檔,一個框架是無用的。由於沒有人會花時間反向工程其規則。

Express.js framework 框架路由語法規則的設計是一個很好的例子,一個很是受歡迎的 web 應用服務器框架。而路由在 web 應用程序中是一個重要的概念,是肯定應用程序如何響應客戶端請求一個特定的端點(一個HTTP方法和一個URI)。Express.js 介紹一個簡單的規則來定義一個路線,app.METHOD(PATH, HANDLER)METHOD 是一個 HTTP 請求方法(例如 GET、POST),PATH 是服務器上的一個 URI 路徑,HANDLER 是回調函數路線相匹配時要執行的。下面的代碼片斷顯示了 Express.js 路由代碼的樣子。

var express = require('express');
var app = express();

// accept homepage request 
app.get('/', function (req, res) {
  res.send('Hello World!');
});

// accept POST request at /user 
app.post('/user', function (req, res) {
  res.send('Got a PUT request at /user');
});

// accept DELETE request at /user 
app.delete('/user', function (req, res) {
  res.send('Got a DELETE request at /user');
});

上面的代碼是不言自明的,由於它像是如何去看一個 HTTP 請求。所以,開發人員只須要不多的努力去學習就記住這個路由語法而且把它的實用性應用到本身的項目中。

總體設計是最糟糕的

這裏的術語「總體」指的是以一個以緊密耦合的代碼庫爲基礎構建的框架。web 框架剛開始流行時,他們每每是一個總體,由於他們的主要目標是提供全方位的快速的 web 應用程序開發。漸漸地,人們意識到總體框架有不少問題。例如,
即便改變是框架徹底無關的一小部分須要從新測試和釋放整個,從而致使應用程序的框架要重建。實際上,總體框架的中代碼耦合使得它很是難以保持不一樣版本的向後兼容性。好比專業緩存、日誌、數據庫,人們變得不那麼願意被綁定到一個單一的總體框架。

現代框架每每是鬆散耦合的體系結構。全棧框架(例如 Spring )已經演變成由鬆散耦合的組件能夠單獨使用或與第三方交換的框架。專門的框架是有明確的契約,以支持更好的互操做性,這使得應用程序不依賴於特定的框架。例如,一個很是受歡迎的 web 路由框架的特色是所謂『Sinatra-type 框架』,如 SinatraExpress.jsMartini。這些框架使用如下中間件管道架構支持請求路由和處理web應用程序。框架自己是很是小的,但開放式體系結構容許他們無限豐富的各類中間件組件。

圖片描述

一致性

一致性意味着一個框架,堅持使用統一的設計,命名約定,代碼風格,代碼組織等等。一個一致性的框架將下降門檻,由於用戶能夠學習框架一個方面,而且應用相同的模式,去快速學習其餘的結構。一致還能夠幫助用戶減小框架特徵錯別字或誤用的可能性。

例如,當設計 Yii 框架的 query builder ,咱們把一致性做爲一個指導標準。查詢構建器(query builder)容許您以編程方式建立一個數據庫無關的 SQL 語句,避免 SQL 注入攻擊。爲了幫助用戶更容易地記住它的 API ,咱們介紹了鏈式接口和命名後相應的 SQL 關鍵字的方法。下面的代碼片斷顯示瞭如何使用 SQL 語句查詢構建器設計。

(new Query())
    ->select('id, email')
    ->from('user')
    ->orderBy('last_name, first_name')
    ->limit(10)
    ->all();

上面的代碼將生成和執行 MySQL 聲明以下:

SELECT `id`, `email`FROM `user`ORDER BY `last_name`, `first_name`LIMIT 10

正如您能夠看到的,代碼讀取很是相似於你編寫 SQL 語句。查詢構建器之間的一致性和 SQL 語法很容易學習查詢生成器。

顯示大於隱式

關於編寫本身的代碼顯式大於隱式,避免過多的使用 「自動魔法」,有兩個緣由堅持這種哲學。首先,顯示的代碼更容易理解和維護。因爲代碼是自解釋的,維護人員可能不是代碼的原做者,不須要來回跳轉找到實際上執行的代碼。其次,顯示的代碼不容易出錯。雖然顯示的可能須要編寫更多的代碼行,它減小了看似簡單含蓄確籠罩着重要的代碼的狀況。

看看下面的兩個 ORM (對象關係映射) 在 PHP 的代碼。他們都但願實現『訂單』數據庫記錄和『客戶』DB 記錄之間創建外鍵引用約束的相同的目標。

$order->link('customer', $customer);

$order->customer = $customer;

第一個版本是正常的方法調用。第二個版本看起來更酷,由於複雜的數據庫鏈接操做能夠經過一個看似簡單的任務來完成。然而,這是一種錯覺,第二個版本的簡單性是由其餘地方的的複雜性隱藏掩蓋。例如,用戶不得不經過某種形式的文檔來學習這種特殊的賦值語法,以便在實踐中使用它。由於連接操做看起來像一個正常分配時,用戶可能會忘記處理由它引發的潛在的異常,從而致使整個程序發生故障。

事實上,Yii 的發展過程當中,關於兩個版本咱們討論了不少,並最終選定了第一個版本,它已收到投訴不多。

約定大於配置

約定大於配置的概念已經存在好多年了。這個想法是一個框架應該採起堅持的公約,遵照約定同時仍然容許經過配置提升擴展性。決策的目標是減小開發人員須要作的數目,從而實現哲學# 1——簡單性。

約定大於配置最先在 Ruby on Rails 框架中開始流行。Rails 提供一個 ActiveRecord 庫,用類和數據庫中的表之間的映射處理。按照慣例,表名是類名的多元化形式。所以,該類帳戶將有一個表稱爲賬戶。若是該表不命名這種方式,用戶將必須顯式配置類名和表名稱之間的映射關係。

許多 MVC 框架使用約定大於配置請求路由到特定的代碼片段。以下圖所示,Sails.js framework 框架使用的約定,其中的 /we/say/hi URL請求將被路由到controllers/we目錄下 SayController 控制器類的hi 動做。按照本約定,開發人員再也不須要對控制器的行爲定義路由規則。可是,若是開發人員想要使用一個不一樣的路由規則,他們仍然能夠經過顯式綁定一個路由到一個控制器動做。

圖片描述

約定優於配置有助於減小須要編寫的代碼量。然而,它會給開發人員須要遵照規則引入了額外的成本。同時,也每每與前面討論的『顯示大於隱式』的哲學相沖突。事實上,雖然早期版本的 Spring 框架使用了似的 Sails.js 路由約定,Spring 如今要求開發者經過註釋明確指定映射。所以,當決定是否引入新的規則以支持約定大於配置,應採起明智的判斷。

總結

建設一個成功的框架是全部關於功能和簡潔性之間的平衡。整個構建框架的過程當中,取捨常常須要以堅守,並舉例說明,上述哲學加以考慮。

有時候,你可能會遇到其中一個理念是與另外一個直接衝突的狀況。一致性是比簡單更重要?在約定比顯性更重要?在這種狀況下,請記住,一個框架的最終目標是簡化開發人員的工做,並簡化代碼的編寫進程。所以,保持它的簡單和直接。若是他們有明確性衝突,由於前者會帶來隱藏的複雜性能夠犧牲約定。一樣,若是堅持一致性能夠稍微違反嚴格會形成額外的併發症。

Posted Dec 15, 2015 by...

圖片描述
Qiang Xue

軟件工程師LEAD、技術人員

首發地址:http://blog.forecho.com/successful-frame...

相關文章
相關標籤/搜索