“约定优于配置”与Magento

约定优于配置(convention over configuration)[1],也称作按约定编程[2],是一种软件设计范式,旨在减少软件

开发人员需做决定的数量,获得简单的好处,而又不失灵活性。

本质是说,开发人员仅需规定应用中不符约定的部分。例如,如果模型中有个名为Sale的类,那么数据库中对应的表

就会默认命名为sales。只有在偏离这一约定时,例如将该表命名为"products_sold",才需写有关这个名字的配置。

如果您所用工具的约定与你的期待相符,便可省去配置;反之,你可以配置来达到你所期待的方式。   

 --来自维基百科的描述

约定优于配置”是一种被很多人所认同的规范,据说当前最火的php框架之一Laravel 就很好的贯彻了这个原则。

那么基于这个原则,来评判下Magento会是怎样呢?

用过Magento的人都知道,Magento的模块配置和模板布局大量的使用了xml来做配置,

这些xml在系统框架启动时会被一起加载然后做各种的xml解析。如果按照“约定优于配置”的标准来看,

Magento的这些xml是否都是有必要的呢?有没有哪些xml项其实可以用约定来代替,而不需要写大量的配置?

这里我找了一个Magento自带核心模块为例,打开Mage_Sendfriend模块的config.xml文件


<config>
    <modules>
        <Mage_Sendfriend>
            <version>1.6.0.0</version>
        </Mage_Sendfriend>
    </modules>
    <global>
        <models>
            <sendfriend>
                <class>Mage_Sendfriend_Model</class>
                <resourceModel>sendfriend_resource</resourceModel>
            </sendfriend>
            <sendfriend_resource>
                <class>Mage_Sendfriend_Model_Resource</class>
                <deprecatedNode>sendfriend_mysql4</deprecatedNode>
                <resourceModel>sendfriend_mysql4</resourceModel>
                <entities>
                    <sendfriend>
                        <table>sendfriend_log</table>
                    </sendfriend>
                </entities>
            </sendfriend_resource>
        </models>
        <resources>
            <sendfriend_setup>
                <setup>
                    <module>Mage_Sendfriend</module>
                    <class>Mage_Sendfriend_Model_Resource_Setup</class>
                </setup>
            </sendfriend_setup>
        </resources>
        <blocks>
            <sendfriend>
                <class>Mage_Sendfriend_Block</class>
            </sendfriend>
        </blocks>
        <template>
            <email>
                <sendfriend_email_template translate="label" module="sendfriend">
                    <label>Send product to a friend</label>
                    <file>product_share.html</file>
                    <type>html</type>
                </sendfriend_email_template>
            </email>
        </template>
    </global>
    <adminhtml>
        <translate>
            <modules>
                <Mage_Sendfriend>
                    <files>
                        <default>Mage_Sendfriend.csv</default>
                    </files>
                </Mage_Sendfriend>
            </modules>
        </translate>
    </adminhtml>
    <frontend>
        <events>
            <catalog_controller_product_view>
                <observers>
                    <sendfriend>
                        <class>sendfriend/observer</class>
                        <method>register</method>
                    </sendfriend>
                </observers>
            </catalog_controller_product_view>
        </events>
        <routers>
            <sendfriend>
                <use>standard</use>
                <args>
                    <module>Mage_Sendfriend</module>
                    <frontName>sendfriend</frontName>
                </args>
            </sendfriend>
        </routers>
        <layout>
            <updates>
                <sendfriend>
                    <file>sendfriend.xml</file>
                </sendfriend>
            </updates>
        </layout>
        <translate>
            <modules>
                <Mage_Sendfriend>
                    <files>
                        <default>Mage_Sendfriend.csv</default>
                    </files>
                </Mage_Sendfriend>
            </modules>
        </translate>
    </frontend>
    <default>
        <sendfriend>
            <email>
                <enabled>1</enabled>
                <template>sendfriend_email_template</template>
                <allow_guest>0</allow_guest>
                <max_recipients>5</max_recipients>
                <max_per_hour>5</max_per_hour>
                <check_by>0</check_by>
            </email>
        </sendfriend>
    </default>
</config>


分门别类的分析下

        <blocks>
            <sendfriend>
                <class>Mage_Sendfriend_Block</class>
            </sendfriend>
        </blocks>
关于block的这段内容给Mage_Sendfriend_Block目录定义一个别名叫sendfriend,单独看这部分好像没什么问题,在看下面这些

<models>
            <sendfriend>
                <class>Mage_Sendfriend_Model</class>
                <resourceModel>sendfriend_resource</resourceModel>
            </sendfriend>

Model目录Mage_Sendfriend_Model的别名也是sendfriend

<routers>
            <sendfriend>
                <use>standard</use>
                <args>
                    <module>Mage_Sendfriend</module>
                    <frontName>sendfriend</frontName>
                </args>
            </sendfriend>
        </routers>
        <layout>
            <updates>
                <sendfriend>
                    <file>sendfriend.xml</file>
                </sendfriend>
            </updates>
        </layout>

前台路由的关键字(也可以算是控制器的别名)也是sendfriend,甚至前台模板布局文件的文件名也是sendfriend.xml


还有一种情况:

        <translate>
            <modules>
                <Mage_Sendfriend>
                    <files>
                        <default>Mage_Sendfriend.csv</default>
                    </files>
                </Mage_Sendfriend>
            </modules>
        </translate>
模块指定的语言包文件的文件名Mage_Sendfriend.csv与模块名Mage_Sendfriend完全一致(不算后缀名)


可以看到,Magento给开发者提供了非常大的自由,可以任意的指定各个目录的别名,各个文件的文件名

等等(比如可以给Block目录和Model目录分别定义不同的别名)。与此同时,Magento所有的自带模块

的配置文件,都与上文的Mage_Sendfriend模块类似,遵守着别名、文件名等都一致的潜规则。

这个规则实际上已经成为了Magento二次开发中的一种编码规范之一(非官方出品的第三方插件

也基本遵循这个规范)。那么回到文章开始的问题,既然大家都在遵守的规范,

能否变成一种约定(代码架构层面),抛弃这部分可能没什么用的自由度。

比如语言包的文件名,代码中直接根据模块名Mage_Sendfriend加上csv后缀去目录里找这个文件,

而不再需要显示的配置来重复指定该文件名。再比如上文提到的别名“sendfriend”和文件名sendfriend.xml”,

能否针对当前模块只指定一次通用的别名sendfriend”,代码上只通过这唯一一个别名来处理各种目录和文件位置,

而不再对各个部分分别去指定一个其实一样的别名或文件名。


变成约定的好处是什么,就像开头的定义所说,旨在减少软件开发人员需做决定的数量。针对Magento,

一方面系统启动时会把所有开启状态的模块的配置文件一起加载到内存中(系统会合并成一个xml),

这个总xml大概一万多行,以约定代替的话,可以大大减少这个xml的总量,另一方面,以约定代替部分配置之后,

整个流程的多个环节不再需要去解析xml来获得内容,对系统性能的提升应该有帮助(江湖传闻,程序解析大量xml是很昂贵的)。


Magento的性能经常被人诟病,系统中大量的xml内容被认为是元凶之一,如果能对这方面做一些优化,

也许会对系统性能有不错的提升。可以看到Magento真的不太符合“约定优于配置”的范式,

应该说Magento的架构设计的太自由(不仅仅指上文的xml配置部分,Magento的自由思想无处不在),

Magento的公司的技术可能是一群极端的偏执狂,估计是一边高喊“不自由毋宁死”一边编码。大笑


前面提到的配置改造成约定,有时间我会尝试玩一下,并且测试下性能上是否有变化。

当然,所谓的改造可能不仅仅局限于xml配置这部分,前面有提到,Magento架构里的自由主义思想无处不在,

按照“约定优于配置”来评判的话,可能还有不少地方可以拿来改造。


不过这个改造基本上还是属于玩票性质,因为按照这个思路改造之后的Magento,

可能都没法直接使用现成的那些第三方插件了(也要改改才能用)。


PS:路由关键词是个特例,某些需求确实需要用在url里的词是人为指定的










你可能感兴趣的:(约定优于配置,Magento)