約定優於配置
約定優於配置(convention over configuration)[1],也稱作按約定編程[2],是一種軟件設計範式,旨在減少軟件開發人員需做決定的數量,獲得簡單的好處,而又不失靈活性。
本質是說,開發人員僅需規定應用中不符約定的部分。例如,如果模型中有個名為Sale的類,那麼數據庫中對應的表就會默認命名為sales。只有在偏離這一約定時,例如將該表命名為"products_sold",才需寫有關這個名字的配置。
如果所用工具的約定與期待相符,便可省去配置;反之,可以配置來達到所期待的方式。
動機
編輯設計不好的框架通常需要多個配置文件,每一個都有許多設置。這些配置文件為每一個項目提供像是URL,或是將類映射到數據庫表的各種信息。大量包含太多參數的配置文件通常是過度複雜的應用設計(代碼壞味道)。[3]
例如,在知名的Java對象關係映射框架Hibernate的早期版本中,將類及其屬性映射到數據庫上需要是在XML文件中的描述,其中大部分信息都應能夠按照約定得到,如將類映射到同名的數據庫表,將屬性分別映射到表上的字段。後續的版本拋棄了XML配置文件,而是使用這些恰當的約定,對於不符合這些約定的情形,可以使用Java 標註來說明(參見下面提供的JavaBeans規範)。
使用
編輯許多新的框架使用了約定優於配置的方法,包括:Spring[4],Ruby on Rails[5],Kohana PHP,Grails[6],Grok,Zend Framework,CakePHP,symfony,Maven,ASP.NET MVC,Web2py(MVC),Apache Wicket。
這是一個古老的概念, 甚至在Java類庫中也可以找出這一概念的蹤跡。例如,JavaBean規範非常多的依賴這一概念。下面摘錄JavaBeans 1.1版規範的一段:[7]
一般來說,我們不希望造出一個碩大無朋的java.beans.everything類用來派生其他類,而是希望JavaBeans運行時為一般的對象提供缺省的行為特徵,但是允許對象通過繼承特定的java.beans.something接口來覆蓋缺省的行為特徵的一部分。[8]
參考文獻
編輯- ^ 也譯作慣例優於配置,慣例優先原則
- ^ Coding by convention
- ^ C2 Wiki (2009-09-01). Too Many Parameters. C2 Wiki, 1 September 2009. Retrieved from http://c2.com/cgi/wiki$?TooManyParameters[永久失效連結].
- ^ Chapter 13.11 describes the application in the context of spring model/view/controller http://static.springsource.org/spring/docs/2.0.x/reference/mvc.html (頁面存檔備份,存於網際網路檔案館)
- ^ http://rubyonrails.org/ (頁面存檔備份,存於網際網路檔案館), advertises the paradigm right from 'home'
- ^ a description of configuration with the goal of convention http://grails.org/Unified+Configuration (頁面存檔備份,存於網際網路檔案館), and relationship to bean referencing from spring 存档副本. [2010-09-29]. (原始內容存檔於2010-10-28).
- ^ Sun (no date). JavaBeans specification, section 1.4. Retrieved from http://java.sun.com/javase/technologies/desktop/javabeans/docs/spec.html (頁面存檔備份,存於網際網路檔案館).
- ^ "As a general rule we don't want to invent an enormous java.beans.everything class that people have to inherit from. Instead we'd like the JavaBeans runtimes to provide default behaviour for 'normal' objects, but to allow objects to override a given piece of default behaviour by inheriting from some specific java.beans.something interface."