`
kongxiantao
  • 浏览: 112977 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

web前端的弱架构导致的代码污染

阅读更多

就要开始新的项目了,全站的前端架构也要开始构思,得益于之前做雅虎关系时的一些或成功或失败的实践总结,还是应当从架构的层面着手,去解决一些前端团队 开发的问题。如今市面上有着各种各样的js库和框架,但库和框架还是有很大区别的,首先,“库”是widget的一个集合,特点是上手容易使用简便,参照 例子只大概只需要引用一个script标签到页面中,再加上一些简单的类似a.start(config)的启动代码就可以了,而框架则是网站的树状结构 的抽象,包括模块关系,功能之间的依赖,入口的先后顺序,以及性能的hack等等,幸运的是阿里还是很明智的选择了yui作为其前端架构的底层,只是由于 yui2强大丰富的widget库,使得多数人认为yui2更是一个库而非框架,而yui2的yuiloader也仅仅是一个可选的模块,这样就更加淡化 了yui2在框架层面灵活强大的表现力,个人认为如果网站没有以yuiloader搭建起来的模块树做支撑,yui2的作用无疑是一把牛刀只用作杀鸡而 已。在yui3中,这种情况有了根本改变,框架层面的模块化代替了简单的库,这对于团队开发的大型网站是很有启发的。

当然,在做前端开发的时候,使用loader必然要多写几行代码,多几次封装,又麻烦又不方便,这样做到底好在什么地方呢。这个话题大概说来话长,这里只从网站规模和项目特点的方面来作简单说明:

像taobao这种大型的网站,前端开发占有不小的比重,这类网站一般会按照大类划分成不同的产品,每个产品相当于一个独立完整的网站,只有整体样式风格和组件会和主战保持一致。

那么从web前端角度讲,这类网站大致包含四部分内容:
1),网站下辖站点所需的全局变量和函数,包括所有子站共通的部分
2),子站外框(公共头尾)
3),网页主体内容
4),组件

根据三者的特点,各自的重用情况为:
1),全站的全局变量和函数:几乎每个页面都要用到
2),子站外框:几乎每个子站的网页都保持一致
3),网页的主体内容,不可重用
4),组件:重用率高,但是被有选择的调用,只在必要的时候才会引用组件

从 需求的角度上讲,这类网站的特点是更新频繁,从工程的角度讲,代码的维护成本大于甚至远远大于代码开发成本。也就是说项目随着时间的推移,修改功能的项目 数量要远远大于新功能的开发,到项目的中后期,工程师的大部分时间不是写新代码,而是花大量的经历去读旧代码,或者进行性能优化,或者针对新需求进行改 进。不管是性能改进还是需求改进,都将增加代码的熵,代码污染也会越来越严重,维护成本也会急剧变大,这让项目后期开发工程师苦不堪言,有一部分原因是项 目前期文档不全,缺少写代码的必要的约束和约定,再者是注释不够及时和规范,导致代码可读性差,三是工程师水平参差不齐,有些人在修改代码过程中会无意识 的破坏原有代码的结构,四是时间压力导致代码质量下降,五是框架结构的不合理。

完善文档和规范、增加新人培训力度可以以解决一部分问题, 但这往往和制度和执行力度有关。从项目生命周期来看,项目分为叠代和快速开发,快速开发是开发时间短,不需要和其他项目并行,及时开发及时测试及时打包上 线,和其他项目发生冲突的可能性很小,简单迭代的开发模式是基于分支和主干的多线程的并行开发。在此基础上的前端开发也是保持和后段开发同步的迭代。迭代 的优点是项目并行和减少冲突的发生。从后端开发的角度看,经常多人开发同一个页面,只是每个工程师负责的模块不同而已,一般情况下页面中只有 include的入口,然后调用各自工程师的代码,这样在页面中的代码污染就比较低,但是随着页面复杂度的增加,后段代码会越来越多的直接出现在页面当 中,比如使用更多的echo代替模版,html代码中嵌套更多的if判断和for循环。这样会增加代码污染的程度。从前端开发来看,也会经常出现多人合作 开发同一个页面,也是每人负责不同的功能模块,这里有两种情况,1是多人同时开发不同的应用模块,两者没有依赖关系,2是多人分别开发框架和应用,两者之 间有依赖关系,应用依赖框架。而两者之间的耦合应当仅仅以入口调用作为接口,因此前端框架应当考虑到这种情况,即多人开发的前端功能代码应当尽可能地分 离。

在js代码的写法上,自然推荐将代码都封装到页面的js文件中,在page中只留出入口。然而实际情况并非如此,在缺少框架约束的情 况下,多数人不会选择去在读懂之前的烂代码的基础上再添加自己的代码,通常会直接用最简单粗暴的用script标签引一个js,紧跟着开一段script 代码块写启动入口,甚至于连script标签都烂的写,直接在原先代码块中直接开辟一段区域自己加代码。这种做法应当如何看待呢?从库的角度讲,库中给了 很多模块的实例,使用模块的方式大都也是手写一个script标签引一个js文件,然后再页面中添加启动入口。那么当多人开发同一个页面中的不同功能的时 候就会这样做:

首先,a在页面中实现了一个功能,大致是这个样子:

<script src="base.js"
 /><!--库的种子-->
<script src="a.js"
 />
<script>
a.start();
</script>


b也实现了另外一个功能,大致是这个样子:

<script src="base.js"
 /><!--库的种子-->
<script src="b.js"
 />
<script>
b.start();
</script>


b在coding的时候多数情况不会去review页面代码,或者说review了页面的烂代码也看不懂,再或者说两个人并行开发,并不知晓对方的实现。这样就会导致base.js的引用重复。

另外一种情况是,如果一个例子比较复杂,需要引用多个js文件,比如:

<script src="base.js"
 /><!--库的种子-->
<script src="a.js"
 />
<script src="b.js"
 />
<script>
m.start();
</script>


那 么a.js和b.js的引用顺序则需要特别注意,但在实际开发中,并不能保证每个人都能细心的将js文件的顺序排好,如果排乱了顺序则需要比较多的调试成 本。所以由此看出,纯粹基于“库”模式的开发会带来很多隐患,这里只提到了开发过程中常遇到的问题,另外,这种手写js标签引用js文件的方式也是缺乏语 义并牺牲了性能(每个script src占用一个http请求?),同时,inline script block散步在页面的各个角落,尽管每个script block都被匿名函数闭包起来,开发速度很快,但这种代码毫无结构性可言,对于其他人也是晦涩难懂,等到项目中后期的维护成本会很高,所以说换作谁都不 愿意去接手维护一个如此coding的项目。因此,可以认为这种coding方式所导致的代码污染会大大降低生产率(这里的生产率包括开发和维护两部分) 和页面性能。

而yui3强制使用Ylaoder,从结构上一定程度的保证代码质量和可读性。按照yui3的思路,项目的前期应当花大精力 去做模块的依赖,在此基础上开发出丰富的widget,使用过程中指需要load模块名字,而不必去关系模块需要依赖那些js,以及这些js的先后顺序是 什么。另外,通过简单hack,loader可以将yui3以及所有项目js都combo在一起(taobao assetcdn现在不提供这种功能,不过很快就会有了),在多的模块都合并到一个js http请求中,外加一个种子,一个页面的js http请求顶多只有两个。

那么是否可以说,象taobao这种复杂多变(需求变更频繁)的大网站就可以用yui3来架构,以避免深度的 代码污染了呢?非也,yui3在设计上并不能满足类似taobao的这种门户。上文提到了网站的四个组成部分,全局、外框、主内容区和组件,他们之间的关 系应当是什么样的呢?显然,页面rander的时候,应当首先加载全局变量,然后初始化load页面所属于的子站的公共头和公共尾,之后再执行页面逻辑, 因此网站三个层次的逻辑关系很明确,所以三者之间必然会发生耦合,框架则需要将这三个层次之间的耦合降到最低,因为,实际情况可能是由很多人同时开发框架 功能、模块、页面主逻辑和底层库的维护,因此就需要每个部分的负责团队的代码相互隔离,以保证并行开发中不发生冲突,鉴于此,纯粹基于yui3的代码结构 有三种:

1,通过YUI().use()的嵌套将层次之间的逻辑关系表达清楚,比如,a的代码属于框架,b的代码属于应用,c的代码属于子应用:

YUI().use(*,function
(){
    //a的代码
    YUI().use(*,function
(){
        //b的代码
        YUI().use(*,function
(){
            //c的代码
        });
    });
});


三个闭包的嵌套,这段代码层次感比较清晰,把a的代码看作框架,b的代码看作应用,c的代码看作子应用,调用关系一目了然,即框架执行完毕后加载并执行应用的代码,应用的代码加载并执行完后执行子应用的代码。

但 三段代码非常紧密的耦合在一块,在团队并行开发中将会经常发生代码冲突。如果代码一次编写不再修改则这种写法并无大碍,往往代码需要经过反复修改,因此这 种显示依赖的编码风格无法避免代码污染的发生。而且最可能b部分的代码是污染最严重的,因为应用可能包含多个子应用,比如产品的列表页御览页和详情页可能 都包含相同的右侧广告位,这样b的代码中就可能包含有平级的多个YUI().use()。

另外一点,每个YUI().use相当于一个loader,每次loader的加载都会将本闭包内需要的模块所对应的js文件加载进页面中,这样如果三次loader的加载有重复的情况则无法去重,造成的不必要的http请求将会增加一倍以上,严重影响性能。

2,一个闭包,各自入口

YUI().use(/*a,b,c的modules*/
,function
(){
    a.start();
    b.start();
    c.start();
});


这 种写法比较精炼,调用顺序一目了然,同样,若代码一次编写不再修改则这是一种不错的写法,考虑到代码的频繁修改,这种方法仍有三个缺点,1,a,b,c都 各自需要引用各自的modules,各自的模块是作为参数写在use的非倒数第一个参数中的,谁也不清楚哪些是a的模块,哪些是b的模块,哪些是c的模 块,这种歧异代码是多人协作项目中必须要避免的。2,a,b,c的代码之间看不出依赖关系,而实际上,框架、应用和子应用之间的调用应当是按顺序,而在代 码维护过程中,a,b,c的调用顺序是可能被修改的。3,三个人写的代码仍然在一起,不敢保证每次修改都会将模块封装致页面中,一旦有人开了先例图省事将 模块代码直接写在了这个闭包中,以后的修改将会一发不可收拾,导致每次需求变更都会更加污染代码。这种情况在雅虎关系的开发中频繁发生,并最终导致代码极 其臃肿,后期即便开发一个类似tabnew的小功能都要耗费半个月时间。

3,各自闭包,互不干扰

YUI.use(*,function
(Y){
    //a的代码
});

YUI.use(*,function
(Y){
    //b的代码
});

YUI.use(*,function
(Y){
    //c的代码
});


三个人写的代码完全分开,不存在相互干扰的问题,再者,即便某个人的代码写的乱七八糟,也不会影响其它人的代码的健康。但缺点有2个,1,象上一节说的代码实际上有依赖关系,这里看不出依赖关系,2,同样的性能问题。

因此如上所述诸多因为框架约束不足带来的代码污染和维护成本增高的现象,应当通过更加强壮的框架来解决。目前正在开发中的cubee框架将会很大程度解决上述问题的发生。

嗯?什么是cubee,cubee有什么用?首先可以确定,cubee是框架,非库,初衷是解决的是团队项目中的代码污染和降低高维护成本,关于cubee的设计详情以后再分享吧。

分享到:
评论

相关推荐

    前端代码如何解耦

    ### 前端代码解耦的关键点 在现代软件开发中,“高内聚,低耦合”的原则被视为提高代码质量的重要指南。对于前端开发者而言,理解并实施代码解耦不仅有助于提升个人技能,还能显著增强项目的可维护性和可扩展性。...

    高粒度模块化的前端开发

    描述:“高粒度模块化的前端开发——WEB前端技术” 根据提供的信息,本文将深入探讨高粒度模块化在前端开发中的应用,以及其如何提升开发效率、代码可维护性和系统性能。高粒度模块化是指在前端开发中,将应用程序...

    web前端工程师 高频面试题

    5. **重绘与重排**:重绘是元素外观改变但不影响布局,重排是元素尺寸或位置改变,导致整个或部分页面重新布局。 6. **缓存策略**:HTTP缓存、浏览器缓存、强缓存与协商缓存。 7. **状态码**:如200表示成功,404...

    携程大前端框架NFES-携程魏晓军.pdf

    - **插件化架构**:支持按需加载,减少不必要的代码加载,提高性能。 - **工具和平台**:提供一整套的研发支持工具和平台,包括开发、测试、发布等多个环节。 #### 四、关键技术实现 NFES在实现过程中,重点解决了...

    掌握了这8个简单的规则你就可以构建一个稳固的可扩展的CSS架构了

    在构建任何Web应用时,CSS架构的稳固性和可扩展性是至关重要的。本文将深入探讨如何根据提供的标题和描述,遵循8个简单的规则来构建一个高效且易于维护的CSS架构。我们将主要关注JavaScript开发中的CSS相关知识。 1...

    microfrontend-experiments:微前端实验

    在微前端架构中,每个小应用(也称为"微前端"或"微应用")都有自己的生命周期和独立的打包过程,它们可以通过某种方式(如路由、API调用或消息传递)进行集成,从而在同一个浏览器窗口内无缝协作。CSS在这个过程中...

    漏洞赏金职业生涯.pdf

    - **Web开发**:具备HTML、CSS、JavaScript等前端技术知识,有助于理解应用程序的架构。 - **编程基础**:对基本的编程概念和语言有扎实的理解。 - **CTF(Capture The Flag)玩家**:通过参与CTF比赛提升实战...

    web-330:JavaScript设计模式

    JavaScript,作为Web前端的主要脚本语言,拥有多种设计模式,这些模式可以帮助开发者更好地组织代码,提高代码的可读性和复用性。 1. **单例模式**:确保一个类只有一个实例,并提供一个全局访问点。在JavaScript中...

    基于JavaScript的多页面打包模板

    JavaScript是一种解释型的、面向对象的、弱类型的脚本语言,主要用于Web和网络应用。它的语法基础是ECMAScript(ES),一个由欧洲计算机协会制定的标准。最新版本的ECMAScript(如ES6、ES7、ES8等)引入了许多新特性...

    microfrontend

    **微前端:构建大型Web应用的新范式** 在现代Web开发中,随着应用程序规模的不断扩大,传统的单体架构模式逐渐暴露出...在实践中,我们需要充分理解其优势和挑战,并选择适合自己的实现方式,以实现最佳的微前端架构。

    新闻发布系统要的来下载啊

    6. **安全性**:系统需要考虑SQL注入、XSS跨站脚本攻击等安全问题,采用预编译SQL、参数化查询等方式避免数据污染。同时,密码应进行加密存储,保护用户隐私。 7. **版本控制**:使用Git进行代码版本控制,便于团队...

    javascript 实例应用

    1. let和const:块级作用域的变量声明,避免了var导致的意外变量污染。 2. 解构赋值:可以方便地从数组或对象中提取值,赋值给变量。 3. 函数默认参数和剩余参数:提升函数参数的灵活性。 4. 箭头函数:更简洁的函数...

    Vue全家桶实践项目总结(推荐)

    在大型应用中,当多个组件共享同一份数据时,Vuex可以帮助协调数据的变更,避免组件间的直接通信导致的问题,如数据同步不一致或内存污染。Vuex引入了“状态管理”的概念,通过创建一个全局的Store,组件只能通过...

    JavaScript语言精粹

    1. **构建工具**:Webpack、Gulp等工具可以帮助自动化前端开发流程,如压缩代码、合并文件等。 2. **测试框架**:Jest、Mocha等工具支持单元测试、集成测试等,确保代码质量。 3. **框架与库**:React、Angular、Vue...

    Fiver.Mvc.FileUpload-master

    在这个项目中,开发者利用了MVC(Model-View-Controller)架构模式来实现文件上传功能,同时结合了CSS技术来美化上传界面,使其在功能性和视觉效果上都有不错的表现。 1. **ASP.NET MVC框架**:ASP.NET MVC是一个...

    ui.js:闭包库的基本UI框架

    3. **内存管理**:闭包可以控制变量的生命周期,避免了全局变量导致的污染和内存泄漏问题。 4. **模块化**:闭包常用于实现模块化,每个闭包函数可以看作一个独立的模块,它们之间可以通过参数传递数据,但不会互相...

    jQuery-Plugin-Wrapper-for-Angular:用于 Angular 的 jQuery 插件包装器

    Angular是一款由Google维护的开源前端框架,它采用MVVM(Model-View-ViewModel)架构模式,强调组件化开发,提供了强大的数据绑定和依赖注入功能。Angular的核心概念包括指令、服务、管道、模块等,这些都与jQuery的...

    Vue.js面试题.pdf

    它专注于视图层,采用MVVM(Model-View-ViewModel)架构模式,通过简洁的API提供了高度可组合的组件化系统。Vue.js的设计目标之一是易于上手且对已有项目的集成友好,同时也能够支持复杂的单页应用。 - **与React的...

Global site tag (gtag.js) - Google Analytics