框架的艺术

  • 框架的意义

    框架存在的意义,必须在实际生产中体会。每一门技术和框架存在的意义都是因为现实的需要,需要解决某一个问题,某一个场景。最近读的一本书,《淘宝技术这十年》,淘宝一开始也不是集成了什么分布式系统,一样是LAMP的架构。技术是根据需求场景和业务而发展的,比如一个学校的一个年级,入学人数只有500的时候设置10个班比较合理,一旦人数增长到了1000(业务增长)之后,发现如果10个班(服务器)每个容纳100个学生(并发)是一件比较吃力的事情,那么就必须增加班级了(扩容),那按照之前的数据一个班容纳50名学生是一个良好的运行环境,这样就需要20个班了。但是哪个学生进入哪个班级(URL分流,负载均衡)需要通过考试或者平均来分配。技术的发展强依赖于现实业务的增长,而技术的发展带来了业务增长空间。

    开发框架,是为了生产者在这个生产模式下极大的提高生产效率,一个好的、通用的开发框架必须囊括了产品所需要的通用功能,比如某公司有统一的商标,则这个商标的生成不需要投入劳力来反复生产。包装需要统一的材料,所以在材料方面尽量使用统一采购接口。任何一项有需要复用的功能,在框架中都应该得以实现。而投入人力的方面,则集中精力的解决业务问题,也就是说产品的功能、产品的包装设计等等无法通过计算来实现泛型设计的部分。Spring带给我们的理念就是,大量重复而臃肿的代码需要统一地实现以减少人力在这方面的投入,使得他们更加专注于他们的核心业务(AOP)。在企业里面的部门有人事、财务、技术等等,他们的工作是互不交叉的(低侵入性),如果一个公司的分工是十分混乱的,那么这个公司的员工肯定是低效的且这个公司是发展缓慢的。

    我们在为掌握的“工具”(Struts、SpringMVC等)而感到激动地时候,更多的应该思考这些“工具”给生产带来了多大的便捷,思考它们的“位置”(控制器、持久层等)。这些技术实现,是为了组成某种产品的零件提供通用的解。MVC的架构实际上就是描述了软件业里面产品的通解:如果一个网站不是MVC设计的,那么它是什么呢?动态网页技术肯定是数据库的读写应用,前端的变幻无穷依然需要控制器去调用模型生成需要的页面。或许我们已经被MVC深深的影响了,如果让我们想一套新的方案,真的可能想不出来更为简洁的了。我相信,即使换了一门语言,它一样有MVC,如果没有,它的设计并不会比MVC更优,有可能杂乱无章。

    重道不重术,是吴军老师在《数学之美》里面给我的启发,练拳要练功,在写代码的同时必须注重思考这些逻辑背后所支撑着的真理。饭前和同事聊天,他说实现前端效果的需要变化需要很多不同的技术,学无止境。窃以为他没有点到本质,技术的变化不是因为需求的变化而变化,我们学习不是学会实现业务的种类(术),而是学习将所有业务都统一实现的逻辑(道)。在我们的教学过程中,特别是数学更有这种指导意义。为什么实数可用x来表示,为什么数列存在通项公式,为什么抽象函数可以表达所有的函数等等。这种由n=1得到值并推广到n得到公式,相对于某个n值来说它就是道,而推导公式的方法对所有公式来说它也是道。越是本质的东西越存在不可替换的特性,所以为什么会有:练拳不练功,到老一场空。时间会把术泯灭,而道却永恒存在。

  • 技术的思考

    关于技术,种类纷繁不胜枚举,每次从阅读官方文档到写demo然后投入生产这一过程的不断重复,期间总会产生一些感悟: 我们总是在学习相似的技术

    就Java而言,它的语法基本上囊括了计算机应用所需要的功能:面向对象、文件读写、网络通信等。它的网络框架无论是SSH、SSM或者其他的如JFinal,它们依旧是实现了相似的功能并且有着同一目的:为了加速生产效率。在Struts风靡一时的时候,并未诞生SpringMVC,这个历史进程中可以得到的结论是,业务量并未提升至需要新框架的地步。而在日益增长的互联网服务环境下,SpringMVC凭借着高开发效率低侵入性还有那特色的注解开发赢得了市场的青睐。任何一门技术总是在效率市场的竞争下不断推陈出新,而它们的目的与意义无外乎解决必要功能之后,提升生产效率。

    对于技术的选种与学习,结合我的经历来谈,在初始学习的时候要尽可能的细致。因为相似的特性存在与不断更新的互联网技术中,在你选择的领域中技术的进化所增加的新特性中,肯定是基于旧框架的功能添加。无论套用多么新潮的词汇或者是取了个让人眼前一亮的名字,在学习的过程中对于它的考察必须基于:历史、特性、解决场景这三个方面来理解和吸收。举个例子,分治法这个算法的特性,就是具有子问题不相互依赖可以分别计算最后合成为总问题的解这么一个特性,所以基于这个原理,具有这个特性的问题就可以使用这个思考模式,如hadoop中一个demo词频统计,因为英文每个词会间隔一个空格,所以它们的统计上是属于相对独立的子问题,在hadoop这个框架下可以轻松统计,而中文的拆分就需要分词器,因为每个字可能和前一个或者后一个有联系生成一个词。

    所以,对制造框架的技术选种,关键是你要解决什么样的问题和场景。对于1000人用户的网站不需要服务解耦,对于编译不到1分钟的项目不需要使用dubbo,对于传说中的修改一行代码编译一个小时的项目需要考虑分布式。花俏的技术不是生产所信仰的宗旨,基于特性的思考才是一个工程师需要具备的素质。

  • 小型框架的诞生

    当今web服务疯长的互联网市场,快仍然是一个不变的要求。如何更快,是架构师们每天的思考。开发框架的诞生通常是结合生产环境而做的设计,对于1000人以下的系统,应用于公司某部门、政府某事业单位、教学等领域,使用传统的MVC模式构建的三层结构是十分足够的。面对大量用户的互联网的需求,分布式和微服务等架构的Web应用随处可见其MVC的踪迹。因此书本上并不会过多的介绍具体设计分布式系统的架构,而只是把概念介绍了一遍。

  1. 三层架构的意义

        如前面所说,框架的意义以及现代框架设计的原则就是让代码更专注于做自己的工作。MVC(Model层、View层、Controller层)模式的设计很符合软件工程的设计美感和框架设计原则。

        如上图架构,视图层专注于向用户呈现计算产生的界面,控制器层负责调度视图层的呈现和从业务层中获取数据,业务层则负责数据库事务和调用模型层进行计算。一个小型网站的访问就是用户从浏览器中输入url,这个url在纯粹的Web应用中就是直接访问到控制器中,由控制器经过计算后吧动态页面通过http协议返回给浏览器,浏览器通过标记语言组成页面。

  2. 根据特性而应用的框架

        在Java Web领域中,未见其人先问其声的当属:SSH。在众多框架中脱颖而出并且占据了MVC市场的三大框架,依据特性来分类的话,对于视图层和控制器层:Struts2、Spring MVC等,对于持久层(Service层):Hibernate、MyBatis等;Spring作为解决依赖关系和精简项目代码的框架而存在,它负责兼容多方框架、构造Bean工程、设置切面、统筹声明式事物等功能,是一个十分优秀的框架“润滑剂”;

        Java Web容器中,存在Tomcat、Jetty、JBoss等免费的Web服务器。它们都是Servlet的容器,遵循JSP规范。源生的JSP技术中,以Servlet为控制器处理Http请求并返回Http响应,页面上也可以通过嵌入Java代码做成动态Web页面。但是由于这门技术的可维护性比较差(主要是页面JSP代码),所以现代大多见的是El表达式、ONGL表达式或者是前后端分离后JavaScript做的数据处理。

        Web应用的本质就是对持久层的操作,所以持久层的存在是十分必要的。源生的JDBC编程可以实现全部的数据库交互,然而繁琐的JDBC代码始终会拖慢开发的效率。为此诞生的ORM框架Hibernate致力于处理对象和数据表的映射,而另一个备受欢迎的框架Mybatis却不是以对象映射而擅长,Mybatis的框架特性是对Sql定制而闻名的,对有Sql优化经验的人来说它是个很好的选择。

  3. 快速开发架构

        如数学公式能定义一类数集映射一样,好的架构应该把人的劳力控制在一定范围内,在程序员对业务进行设计的时候不需要思考构造架构的组件。对于小型网站而言,笔者的经验总结它通常有两个入口去访问这个网站。某些控制器是return page的而另一些是resturn json data的。所以有些时候你访问一个网站失败了,会在页面上打印{...}这种数据。对于控制器的设计,架构应该提供页面规范和接口规范,即 域名/Web应用名/接口(页面)这样的访问形式会返回页面或者是Json数据。采用当下最流行的RESTful架构风格,接口只需要根据url参数来进行相应的数据返回。比如博客园的https://i.cnblogs.com/用户名/p/(id名)则是从文章数据库中查询相应的文章,但是它并不暴露所传递的参数,与平时常见的GET请求有所区别(如果是常规GET请求:https://i.cnblogs.com/用户名/p?id=...)。

           Spring MVC良好地提供了一种RESTful的风格的接口编写。

    

package Test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import Common.Controller.OutputStringController;

@Controller
public class Hello extends OutputStringController{
    //接口形式
    @RequestMapping(value="/Hello",produces="text/html;charset=UTF-8")
    @ResponseBody
    public String sayHello(){
        System.out.println("访问了Hello!");
        return failure("失败");
    }
    //restful接口
    @RequestMapping(value = "/start/{name}", produces = "text/html;charset=UTF-8")
    @ResponseBody
    public String start2(@PathVariable("name") String name1) {
        System.out.println(name1);
        return "start";
    }
}

  • 服务端架构设计

    针对小型网站的设计,重心依然放在与数据库的交互和呈现页面给用户这部分上。而变化多端的业务程序必须由人力来完善,在处理事务的过程中,必须保证数据从用户到数据库的正确性,所以把事务应用于Service层。在用户操作数据的过程中,每一个结果必须具体告知用户(是否已存储数据、数据是否合法、是否发生了异常而导致数据有损)。用户登录后台检查录入数据的页面必须友好易懂,在页面加载过程中等待的时间尽可能控制得越低越好,所以在表设计的过程中以及SQL的编写必须再三斟酌。

    网站的配置文件尽可能不去改变,因为一个小小的改变有可能会导致蝴蝶效应。可以更改的部分仅仅是数据库的更换,数据库账号密码等。

    网站的公共功能需要根据项目的需求进行完善,对于小型网站的功能可以列举的是:启动自动建设对象和表的映射、启动定时任务、JavaEmail的发送、登录过滤等等。

    业务层的设计规范,依托Spring提供的事务模型,如果需要aop再行配置。对于表设计,尽可能使用单表设计,而表关系尽可能使用程序逻辑来实现,事务的设计笔者采用下图所示。

    网页资源在WebContent中,网页一般有静态页面、图片资源、CSS样式、JS代码以及JSP页面。

    网页路由采用访问控制器后返回Web应用下级资源,控制器有如下形态。

/**
 * 主页控制器
 * @author ctk
 *
 */
@Controller
public class IndexController {
    @RequestMapping("/index")
    public String index(){
        return "index.jsp";
    }
}
    <!-- configure the InternalResourceViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
            id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="jsp/" />
        <!-- 后缀 -->
        <property name="suffix" value="" />
    </bean>

    在return的字符串中,会加上前缀jsp/,这样访问接口资源就会定位到jsp包下。

    如果直接访问页面,则不会加载出样式。如果不想用户直接访问,使用Interceptor过滤掉用户的请求即可。

  • 小结

    这套框架是从工作中总结而来,虽然在当今分布式横行的环境中可能不具备什么优势,但是经典结构是Web技术的基础,无论如何服务解耦都逃不过MVC的影子。读到书上说的URL分流,其实就是在控制器前加一个负载均衡器,用户访问同一个名字的接口会由中间件选择负载较轻、响应较快的节点返回资源,而在Web应用发展到编译一次半天过去了的情况,则会把Web应用中的Service层解耦。相对独立的Service会形成一个提供服务的中心,提供某种服务(用户资料中心、商品中心等)。他们的信息交互有可能使用到消息队列,一切都是大型网站发展的必然趋势,然而分布式只是拆应用,并没有拆掉他们的本质,对于网站架构,笔者仍然有很长的路要走。

时间: 2024-10-10 13:18:57

框架的艺术的相关文章

【源码分享】WPF漂亮界面框架实现原理分析及源码分享

1 源码下载 2 OSGi.NET插件应用架构概述 3 漂亮界面框架原理概述 4 漂亮界面框架实现  4.1 主程序  4.2 主程序与插件的通讯   4.2.1 主程序获取插件注册的服务   4.2.2 插件获取主程序注册的服务   4.2.3 服务接口  4.3 权限管理插件的登录窗体  4.4 界面框架插件   4.4.1 导航服务   4.4.2 界面框架扩展实现  4.5 插件   4.5.1 插件引用了第三方程序集   4.5.2 一个程序集如何让所有插件都直接使用   4.5.3

.NET服务端开发—多线程使用小结(多线程使用常识)

有一段时间没有更新博客了,最近半年都在着写书<.NET框架设计-大型企业级框架设计艺术>,很高兴这本书将于今年的10月份由图灵出版社出版,有关本书的具体介绍等书要出版的时候我在另写一篇文行做介绍.可以先透露一下,本书是博主多年来对应用框架学习的总结,里面包含了十几个重量级框架模式,这些模式都是我们目前所经常使用到的,对于学习框架和框架开发来说是很好的参考资料,大家敬请期待. 好了,进入文章主题. 最近几个月本人一直从事着SOA服务开发工作,简单点讲就是提供服务接口的:从提供前端接口WEBAPI

ASP.NET Web API 控制器创建过程(一)

ASP.NET Web API 控制器创建过程(一) 前言 在前面对管道.路由有了基础的了解过后,本篇将带大家一起学习一下在ASP.NET Web API中控制器的创建过程,这过程分为几个部分下面的内容会为大家讲解第一个部分,也是ASP.NET Web API框架跟ASP.NET MVC框架实现上存在不同的一部分. ASP.NET Web API 控制器创建.激活过程 ASP.NET Web API 控制器创建过程(一) ASP.NET Web API 控制器创建过程(二) 未完待续 环境描述.

ASP.NET Web API 开篇示例介绍

ASP.NET Web API 开篇示例介绍 ASP.NET Web API 对于我这个初学者来说ASP.NET Web API这个框架很陌生又熟悉着. 陌生的是ASP.NET Web API是一个全新的框架,对于这个框架在一个项目中起到的作用我暂且还不是很清楚这里也就不妄下结论了,说实话不是我不想而是我无能为力,只能自己去摸索试着去了解它. 熟悉的是ASP.NET Web API跟ASP.NET MVC的框架结构一开始看起来有一些相似的地方. 话就不多说了,大家就和我一起来学习ASP.NET

JAVA并发编程的艺术 Java并发容器和框架

ConcurrentHashMap ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成. 一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap类似,是一种数组和链表结构, 一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素, 每个Segment守护者一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segmen

TensorFlow【机器学习】:如何正确的掌握Google深度学习框架TensorFlow(第二代分布式机器学习系统)?

本文标签:   机器学习 TensorFlow Google深度学习框架 分布式机器学习 唐源 VGG REST   服务器 自 2015 年底开源到如今更快.更灵活.更方便的 1.0 版本正式发布,由 Google 推出的第二代分布式机器学习系统 TensorFlow一直在为我们带来惊喜,一方面是技术层面持续的迭代演进,从分布式版本.服务框架 TensorFlow Serving.上层封装 TF.Learn 到 Windows 支持.JIT 编译器 XLA.动态计算图框架 Fold 等,以及

框架模块设计经验总结

转自:http://www.cnblogs.com/zgynhqf/archive/2011/07/15/2107593.html 这是原创,尊重原创............ 框架模块设计经验总结 三个月没写日志了,比较懒散--下半年准备做OEA 的 B/S 版本,比较复杂,需要从架构设计开始认真入手.正好今天到了部门反思的时间,今天先把原来的一些设计经验总结一下,以方便将来回顾. 直入主题,这篇日志主要用于总结一些框架级别的模块设计经验. 总述 一个大型的框架,必然由多个较独立的子系统/子模块

java 框架 面试 2

1.谈谈你对Struts的理解. 答: 1. struts是一个按MVC模式设计的Web层框架,其实它就是一个大大的servlet,这个Servlet名为ActionServlet,或是ActionServlet的子类.我们可以在web.xml文件中将符合某种特征的所有请求交给这个Servlet处理,这个Servlet再参照一个配置文件(通常为/WEB-INF/struts-config.xml)将各个请求分别分配给不同的action去处理. 一个扩展知识点:struts的配置文件可以有多个,可

2017 框架、框架、类库、类库,web前端应该学什么 ?

在当今的快节奏生态中,有人倾向于花时间尝试最新框架,最新的类库,新奇有趣的插件.. 但我们的确应该把脚步放慢一些,并认真了解那些不会有很大变化的事情(理论本质).这样不仅会提升我们的工作质量和我们所创造的价值 -- 还将切实地帮助我们更快理解这些新的工具. ### 如何写出可读性高的代码 我们多数的工作并不是编写新代码,而是维护已有代码.这意味着你最终阅读代码的时间要比编写它所花费的时间要长,所以你需要为之后需要阅读你代码的程序员优化代码,而不是为了解释器. 这里我建议你按以下顺序 - 由浅入深