分离与模块化:分工合作,各司其职


在目前的编程开发的教学中,大家往往关心的是语言、语句、对象等概念和编写方法,却往往忽视了开发思想的构建。接下来的文章中,我会向大家介绍一些重要的开发思想。不过,这些思想实际上并不仅仅属于开发,还属于其他的方面,所以对于非开发者而言,也很重要。

这个文章中,我将介绍的是:分离与模块化。

从课设报告开始

某一堂课的期末作业是以小组为单位,交一份关于开发管理信息系统的课程设计报告。宿舍里面的四个人正好组成一个小组,如何完成这次课程设计报告呢?

大家最容易想到的解决方案就是:每个人负责报告的某部分。比如:A负责写可行性分析,B负责写系统分析,C负责写系统设计,D负责写系统实施。然后把大家写的各部分合并起来。当然,这是理想情况,实际上一些部分需要在其他部分完成之后才能进行。

4个部分

这就是团队合作,是分离与模块化的一个典型的例子。在这里,我将这两个词放在一起,是因为:“分离”如果不能达成模块化,那么它毫无意义;为了实现“模块化”,分离是必需的。上面的例子中,我们将一份课程设计报告分离成了可行性分析、系统分析、系统设计、系统实施四大模块,每个模块互相独立,有着自己的功能,却又是整体的一部分,与其他模块之间存在关联。

在生活中,这样的例子十分多见,如:电脑的硬件分成了CPU、主板、内存条、硬盘等可插拔的元件;生产线以模组为单位进行各个工序的处理;一套健身流程由多个子动作按规律装配而成。

Keep上的某个训练

人们运用分离与模块化的原因并不是单一的。写报告中的分离与模块化,是为了平衡工作量、减轻负担;电脑硬件的分离与模块化,是为了能够较为方便地更换硬件,方便电脑的组装、升级与维修,方便个性化定制;生产线中的分离与模块化,是为了方便维修更换,能够在一个工序出现异常时,将对其他工序的影响降到最低;健身中的分离与模块化,是为了方便教学、充分发挥各子动作的优势,让健身更加高效。虽然具体原因各不相同,但是总的来说,无非是为了提高效率、方便安装、更换与定制、减少单个问题对整体造成的影响。

南京LG化学工厂更换流水线上的设备,机器模块化特征明显

开发中的分离与模块化

在开发中,这个情况更为多见了。

最显而易见的例子是网页制作中,内容(HTML)、样式(CSS)与动作(JS)的分离。

我们的“电子商务网站开发与建设”的课程设计中,由于我底子比较好,就给很多同学提供了帮助。我在写代码的时候比较注重分离的思想,开发出来的网站还算不错,后期修改起来也挺容易。但是其他同学的就不一样了,改他们的代码对我来说显得异常艰难。

样式与内容分离

我看到有很多同学把样式写在标签里面,如:

<div style="padding-bottom: 5px">
    <h1 style="color: #22842C;font-weight: normal;margin: 15px auto 9px auto">用户登陆</h1>
    <div>
        <p style="display: flex;width: 100%;margin: 9px 0;font-size: 1.1rem;justify-content: space-between">
            <label for="username">用户名:</label>
            <input type="text" name="username" id="username" pattern="1[0-9]{10}" value="" style="margin: 4px 45px 0 0;height: 15px">
        </p>
        <p style="display: flex;width: 100%;margin: 9px 0;font-size: 1.1rem;justify-content: space-between">
            <label for="password">密码:</label>
            <input type="password" name="password" id="password" pattern="[A-Za-z0-9]{6,12}" value="" style="margin: 4px 45px 0 0;height: 15px">
        </p>
        <div>
            <button id="login" style="margin: 0 20px;height: 30px;width: 60px;font-size: 1rem">登陆</button>
            <button id="register" style="margin: 0 20px;height: 30px;width: 60px;font-size: 1rem">注册</button>
        </div>
    </div>
</div>

(这是我拿自己写的代码改的,那些同学写的更加惨不忍睹)

这会让标签变得非常长,而且对于一些要经常使用的组件也这么写,会让样式的调整变得相当困难。

解决方法就是:除非确有必要放在标签里面,将关于样式的内容全部从标签里面分离开来,放在一起,在原来的位置以对应的classid属性替代,当然也可以充分利用CSS的选择器标识需要应用样式的元素,如:

<div class="login">
    <h1>用户登陆</h1>
    <div>
        <p>
            <label for="username">用户名:</label>
            <input type="text" name="username" id="username" pattern="1[0-9]{10}" value="">
        </p>
        <p>
            <label for="password">密码:</label>
            <input type="password" name="password" id="password" pattern="[A-Za-z0-9]{6,12}" value="">
        </p>
        <div class="login-button">
            <button id="login">登陆</button>
            <button id="register">注册</button>
        </div>
    </div>
</div>
.login {
  padding-bottom: 5px;
}
.login > h1 {
  color: #22842C;
  font-weight: normal;
  margin: 15px auto 9px auto;
}
.login > div > p {
  display: flex;
  width: 100%;
  margin: 9px 0;
  font-size: 1.1rem;
  justify-content: space-between;
}

.login > div > p > input {
  margin: 4px 45px 0 0;
  height: 15px;
}
.login-button > button {
  margin: 0 20px;
  height: 30px;
  width: 60px;
  font-size: 1rem;
}

至于样式放在哪里,有两种选择:一是放在<style>标签中,二是放在一个单独的CSS文件中,在HTML中用<link>标签引入。

样式与内容分离的两个方法

我推荐放在单独的CSS文件的做法。为什么呢?

第一,放在单独的CSS文件中,能够让代码看起来更加简洁。

第二,如果有不同网页的一些组件需要使用同样的样式,就可以只写一遍代码,而不用每个网页写一遍样式,修改起来也非常方便。

通常情况下,一批网页中,有样式相同的地方,有不同的地方。我们将公用的样式放在一个或多个CSS文件里面,将自有的样式放在另一个CSS文件里面,在HTML文件里面引用公用的样式和自有的样式就可以了。这就是样式的模块化。

样式的模块化

动作与内容分离

同样的情况也可以适用于动作。

我在看同学的代码的时候经常见到这样写动作:

<div class="login-button">
    <button onclick="login()">登陆</button>
    <button onclick="register()">注册</button>
</div>

<script>
    function login(){...}
    function register(){...}
</script>

(这已经非常简化了,有很多人都是样式、动作写在标签里面的,代码不堪设想)

虽然这样写可以运行,但是代码的可读性、可修改性明显下降了。如果我来写,会这样写:

<div class="login-button">
    <button id="login">登陆</button>
    <button id="register">注册</button>
</div>
document.getElementById('register').onclick = function() {...};
document.getElementById('login').onclick = function() {...};

对了,和样式类似,最好把动作单独放到一个JS文件里面,在HTML文件中用<script>标签引入。

当然,你也可以这样写JS:

function login(){...}
function register(){...}
document.getElementById('register').onclick = login();
document.getElementById('login').onclick = register();

如果函数需要重复使用,这种情况显然更好。

和CSS类似,这样分开写的方法,也可以做到模块化。

样式、动作的模块化

简而言之,这样写的最大的好处就是方便自己看代码、写代码、改代码,其次还可以方便他人——由于文件可复用,传输的流量也能够大幅减小。

不仅仅是网页开发

我们将有着一定功能、需要经常复用的组件从程序中分离出来,就构成了一个模块。我们在写其他程序的时候,就可以导入、使用这些模块,而不需要复制冗长的代码,不需要考虑重名等头疼的问题。Python和JS最近发展迅猛,有一个很重要的原因就是有着大量的第三方模块支持,开发者像搭积木一样写代码,大大提高开发效率,也节省了大量的时间和精力。

Ant Design Pro中一例,选中部分为导入的模块

学开发的人经常听到一个架构模式:MVC,即模型(Model)、视图(View)、控制器(Controller)的分离。还有MVP,即模型、视图、展示器(Presenter)的分离;MVVM,即模型、视图、视图模型(View Model)的分离;还有前后端分离。它们都是开发行业中,分离与模块化的典范,与语言无关,许多语言都可以使用这样的模式开发项目。

但是,我们往往看不出它们之间的差别,毕竟模式太像了。不过,我们只要记住,它们都是为了方便开发而生的。

我们拿MVC来举例子。人各有所长,如果一个项目把模型、视图、控制器都放在一起,不加分离,那么意味着如果一个小组的所有人都需要精通这三个方面的知识,才能完成、维护项目。如果分离,小组里面每个人负责自己擅长的部分——有人擅长图形界面的编辑、有人擅长数据模型的搭建、有人擅长逻辑操作——大家不需要对这三样事物都精通,只需要精通自己最擅长的一项事物就行了。这样也能大幅减少学习时间,提高团队开发效率。其他的模式也差不多,万变不离其宗。

分离与模块化还有一大优点:不同的开发者可以使用不同的语言完成一个项目。前面也说过,人各有所长,你精通的语言别人可能一窍不通,别人精通的语言可能你也一窍不通。但是,如果让项目之间各个部分分离,每个人负责特定的模块,不同语言写的模块使用相同的格式(如JSON)传递数据,照样也能出色地完成任务。

总之一句话,“上帝的归上帝,凯撒的归凯撒”。不管是在开发中,还是在生活中,分离与模块化都是重要的思想。


文章作者: 丁俊尧
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 丁俊尧 !
  目录