大话代码架构:项目实战版(txt+pdf+epub+mobi电子书下载)


发布时间:2021-08-04 05:38:30

点击下载

作者:田伟,郎小娇

出版社:机械工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

大话代码架构:项目实战版

大话代码架构:项目实战版试读:

前言

架构(Architecture)是什么?可能每个人给出的答案都不同。业界流行一句笑话:

Architecture is like teenage sex,everybody talks about it,nobody really knows what it is.

当然,MOL也不可能给出一个关于架构的准确定义。MOL更愿意把架构归为哲学的范畴。架构本身其实和软件开发并无太大关系。一个国家有自己的管理体系;一个公司有自己的组织架构;一个家庭也有独特的男权或女权的特色,小到一个人;也是可以分为自我、本我和超我的。每个事物都是由一个个更小的事物组合而成的,而这些其实都与架构相关。

在宏观世界里,所有的国家公民构成了一个国家主体,国家主体对每个公民进行管理和约束,这是架构。

在微观世界里,电子绕着原子核高速转动,始终不会脱离原子核的管辖范围。而原子核和电子又组成一个原子。原子对电子、质子、中子的管理就是架构。

本书的读者一定是软件行业的高手或菜鸟,那我们就回到软件编程的世界里。

每个软件项目都是由代码和服务器构成的,如何统筹安排代码和服务器,就是架构的范畴了。

一个项目可能要使用多台服务器,如Web服务器、数据库服务器、文件服务器、CDN……如何针对不同的要求对服务器进行选型,这是架构;如何统一管理这些服务器,这是架构;如何让这些服务器平稳运行,这也是架构。

开发项目使用什么语言,是Java还是Node.js?选用什么数据库,是Oracle还是MongoDB?这是架构。

具体到开发过程中,某个模块应该如何安排,是交给DBA(数据库管理员)用存储过程来实现,还是让C#程序员访问数据库实现?这是架构。

在写C#代码的时候,采用三层架构,还是MVC?这是架构。

如何写日志,是使用I/O读写文件?还是采用log4net?或者是AOP切片写日志?这是架构。

甚至具体到某种技术的时候,也有架构。比如MOL规定项目要使用MVC架构,那么使用微软的MVC,还是Spring的MVC?这都是架构。

可见,架构涉及的范围非常之广。弱水三千,MOL只给一瓢。本书将从代码架构的角度来让大家一窥架构的真面目。

C#是一门非常优雅的编程语言(当然MOL并无编程语言的偏见),所以本书中所有的代码都以C#语言来描述。

本书特色

1.风趣幽默

MOL一直比较反对平铺直叙的讲解方式,所以本书的语言风格是比较幽默的。在本书的内容中将出现3个与MOL并肩作战的兄弟(公司老大邓总不在此列),以对话形式抛出问题并解决问题。

2.案例分析

本书中只有一个项目“晋商卡”,但MOL会带着大家见证“晋商卡”从无到有的过程,大家可以在这个过程中获得很多意想不到的收获。

3.向循规蹈矩说NO

正如MOL在结语中所说,2017年是一个强调“工匠精神”的一年。几乎所有的人都在精益求精地做自己的事情。但MOL要分享给大家的是一种懒人精神,我们不愿意日复一日地重复昨天的自己,我们要站在更高的层面,做更少的事情,却有更多的收获。

本书内容及体系结构

第1篇 需求与三层架构(第1~3章)

本篇详细介绍了项目开发的前置节点——需求,并对常见的三层架构给出了分析。在第1篇中提出了面向对象的重点概念,并让大家初步认识抽象的过程。

相信很多人一定被书中大段的SQL代码搞得云里雾里,不用担心,在第3章中MOL将带领大家完成懒人的第一步——如何不写SQL代码。

第2篇 NoSQL和测试(第4、5章)

NoSQL是现在比较流行的一个话题和技术。在第4章中将通过讲解MongoDB来介绍NoSQL如何使用,并且纠正大家的一个错误观念:NoSQL和ORM不能搭配使用。

第5章分享了测试的工作,并讲解了单元测试、黑盒测试、白盒测试……让大家在收获的同时,也能理解测试工程师在工作中所要面临的一些痛苦。

第3篇 高精尖技术(第6~9章)

任何一个网站项目,似乎都绕不开“缓存”这个神奇的空间。缓存用得好,可以加快系统的反应速度。如果缓存用得不好,不仅用户体验差,还可能造成服务器宕机。第6章就分享了如何使用缓存。

每个程序员都有一个全栈的梦想,而前端又是全栈中必不可少的一部分,第7章讲解了如何使用EasyUI来搭建前端。

现在越来越多的电商网站都会做一些抢购或促销活动,当然这就使得网站不可避免地面临高并发。如何处理高并发呢?第8章将通过讲解消息队列,来说明如何应对高并发。

微信已经成了人们生活中必不可少的一部分。在2017年3月27日这一天,微信小程序也对个人用户开放了。我们如何把“晋商卡”挂到微信公众平台上,又如何开发微信小程序呢?这些问题都将在第9章中解决。

本书读者对象

·对代码架构感兴趣的初学者;

·对代码架构感兴趣的爱好者;

·高校学生和相关培训学校的学员;

·初入职场需要提高开发水平的开发人员。

因为书中所有的代码都以C#语言来描述,所以本书读者如果有一定的C#语言基础更佳。

本书配套资源及获取方式

为了方便读者高效地学习,本书特意提供了以下配套资源:

·本书源代码文件;

·本书涉及的一些开发工具的安装包。

这些配套资源需要读者自行下载。请读者登录机械工业出版社华章公司的网站www.hzbook.com,然后搜索到本书页面,按照页面上的说明进行下载。

本书作者

本书主要由田伟(就是笔者MOL)和郎小娇主笔编写。其他参与编写的人员还有李小妹、周晨、桂凤林等。

读者阅读本书时若有疑问,可以发邮件到hzbook2017@163.com以获得帮助。引言

我叫MOL,如果你是MOL的读者,那么一定知道“摩丝”了。MOL者,“摩尔”也。摩丝者,MOL的粉丝也。MOL在本书里将带领大家一起做一个属于自己的代码架构。

代码架构和架构是一样的吗?且看MOL如何分解。

一谈到架构(Architecture),大家一定会觉得它是一个非常“高大上”的东西,当然,大部分人都是这样宣传的。为了让大家有一个更好的感性认识(因为本书并不是讲架构的,所以只要有感性认识就可以了),MOL决定用一个简单的例子来告诉大家什么是架构。一个架构师的例子

在2015年的时候,MOL主导了一个B2C(Business-To-Customer,商家对客户)网站,MOL在这个项目里面充当了非常多的角色,如产品经理、项目经理、架构师、DBA(数据库管理员)、程序员、QA(质量管理员)、Tester(测试员)……现在来看一下MOL作为架构师时所做的事情。

MOL作为架构师,是以大体需求为前提的,也就是说,我们在这里不去讲如何获取需求,因为这不是架构师份内的事。当MOL拿到需求以后,就可以进行架构了。架构大体上分为两部分:硬架构和软架构(这并不是标准的叫法,只是想让大家更好地理解架构)。

1.硬架构

顾名思义,硬架构就是关于硬件的架构。MOL根据目标用户量和业务要求,采购了3台服务器,分别作为文件服务器、数据库服务器和Web服务器(同时兼任缓存服务器),同时,建议用户在客户量增加到一定数量级以后,增加CDN(Content Delivery Network,内容分发网络)服务器,以加快访问速度。

OK,架构师的输出已经完成了。但大家以为架构师就买几台服务器就完事儿了吗?那就大错特错了。在买服务器的背后,MOL对需求进行了研究,分析了网站需要承担的平均访问量和网站的业务内容。这个网站的访问量并没有大到令人发指的地步,所以我们暂时不用考虑硬件负载均衡的问题,只需要提供一台Web服务器就可以了。这台Web服务器需要处理用户发来的请求并做出响应给用户。为了提高Web服务器的性能,我们将会在这台Web服务器上安装虚拟机,并用Nginx(一个HTTP服务器,类似于IIS)做软负载均衡。

由于本系统中需要保存大量的用户文件,如果把这些文件都放在Web服务器上,那会给软件负载均衡产生额外的负担,并且大量的文件很容易把一台服务器“撑爆”。所以,我们用一台服务器专门来保存文件信息,这台服务器就叫文件服务器。

数据库是一个项目中必不可少的一部分,数据库的本质其实就是文件和内容的组合,所以数据库的空间增长也是不可小觑的。而且数据库的操作,将会耗费大量宝贵的CPU和内存资源。所以我们将数据库专门放在一台服务器上,这台服务器就叫数据库服务器。

好,硬件资源采购完成了,我们要把它们组合到一起。Web服务器向网络公开,让用户可以访问,而文件服务器和数据库服务器只在局域网中,并不对外公开,这样可以在一定程序上保证安全性,而且也为客户节省了费用。Web服务器可以访问文件服务器和数据库服务器。

其实硬架构是非常复杂的,但本书不是主要讲硬架构,所以这里讲得非常简单,有兴趣的读者可以自行找“某度”或“某狗”进行搜索。

2.软架构

本系统将采用.NET平台下的C#语言进行开发,采用SQL Server数据库,使用微软的Cache缓存配合Redis来做。前台将以3种终端展示,分别是PC、手机、平板。所以前端将会使用HTML 5来做。Android手机APP使用Java语言来开发,iOS平台上的APP暂时不做。

同样的,软架构也只是让大家看到了输出,并没有讲为什么这样做,因为这也不是本书的重点。

上面粗略地讲了一下什么是架构。下面来具体看一下代码架构。废话不多说,直接来看图1和图2。图1 正常的代码架构图2 不普通、非文艺的代码架构

图1是一个常见的代码架构,而图2可能是新手程序员最喜欢的“代码结构”。代码架构的目的是让不同的代码块去干不同的事,最后再把这些代码块整合在一起,组成一个项目。这是本书要讲的内容。

可以看到,代码架构和软件架构基本上不属于同一个层次的元素。但不可否认的是,代码架构是一个程序员应该具备的技能,也是通往架构师的必经之路。

PS:各位读者可能对用户和客户这两个概念理解有误,这里统一一下,用户(User)是指使用系统的人,客户(Customer)是指要求我们做这个系统并且支付开发费用的人。背景及人物介绍

本书中,我们将延续MOL活泼幽默的风格。为了剧情的需要,书中将会出现5位主人公。

MOL:姑且称之为老鸟吧,从事代码工作多年,在公司中主要负责项目管理和代码架构。

邓总:公司老大,身材消瘦如马云,有一双深邃的眼睛。虽然是公司的老大,但在本书中出现的次数并不多。

刘朋:新入职员工,因为名字中的“朋”字“占地”面积很大,所以大家一般都会把“朋”字分开来念,所以他有另一个名字“月月”,性格比较幽默。

岳鹏辉:新入职员工,长得比较帅气(已有女朋友)。

李冲冲:新入职员工,打得一手好乒乓球。

这几位主人公将会在本书中出现,他们可能是说相声的,可能是打酱油的,也可能是回家跪搓衣板的。但是他们更重要的作用是构造一个个生动的故事,在这些故事里面,大家可以看到一个真正的项目是如何搭建的。

故事来源于生活,却不高于生活,这里的人是真实的,故事是真实的,当然,最重要的是,项目是真实的,知识也是真实的。MOL尽量用最接地气的语言,最平实的故事,来讲述一个个“高大上”的知识和技术。我们的目标

我们经常会听到这样的话:“加班不是目的,目的是不加班”。这样的话让人无比窝火,但又无比正确。我们还会听到这样的话:“我这样严厉地要求你,是为了让你成长得更快”。你有理由反驳吗?其实,换一种方式,我们可以快乐地成长。这也是MOL带团队的宗旨,也是本书的目的。MOL要让你快乐地看完这本书,最后发出的感慨一定是:“代码架构其实挺简单!”

好了,我们要开始了!第1篇需求与三层架构·第1章 故事从一个电商网站开始·第2章 为什么是三层·第3章 ORM实体关系映射第1章 故事从一个电商网站开始

按照惯例,一本书的开始一般会介绍一些基础知识,如Java语法、XML结构等。相信很多读者都立志做一名“高大上”的Coder,但是一看这种开篇讲语法的书就先泄气了。为了不让大家泄气,我们将使用一个电商网站项目来作为开篇。

说到项目,大家一定会想到某培训机构的机票管理系统、通讯录……估计大家都要被这些标题党搞疯了。这些听起来很好听的系统,不一定有什么实用价值。但是我们要介绍的项目,是一个实打实的、已上线的、微信上可查找的一个项目。如果各位摩丝在任何时候觉得学习有点累了,或者迷茫了,可以上微信搜索“川商卡”,这就是我们要讲的系统。MOL在做这个系统的时候,用到的技术并不多,像缓存、消息队列等这些技术在项目中没有出现,但在本书中MOL也会讲到。MOL可以很负责任地说,当大家学完这本书后,可以毫不费力地给自己快速搭建一个“高大上”的代码框架。

下面的内容,将是一些非常杂乱的、与代码看似无关的基础知识,请大家耐心看完。1.1 需求?需求!

相信大家对一些翻译软件的使用已达到炉火纯青的地步了,如果把“需求”这个词输入翻译软件,会出来一大堆对应的英文单词。这里只挑两个容易混淆的单词来说,即Request和Demand。

通常出现需求的地方,一般都会用Demand来描述,但是偶尔也会看到Request。这两个单词都是需求的意思,有啥区别嘞?

Demand是必须要完成的,没有商量的余地。比如你的BOSS告诉你:我们的项目要加入某宝支付的功能。这就是Demand。虽然过两天BOSS有可能把这个功能“砍掉”,但是令行禁止,你还是必须得把某宝支付的功能实现。

Request是锦上添花的功能。比如你的BOSS是一位单身宅男,他问你:在网站某个页面的右下角加入一个美女的图片,可以吗?这就是Request,它表示请求。也就是说,你不加这个图片,项目照样运行。至于这个图片是否要加,那就看你的心情喽。

下面,我们来描述一下本书中的项目需求。

由于本书中的项目采用的是敏捷开发,所以开发过程中的文档特别少(关键文档是不可以省略的)。这里不可能列出所有的需求文档内容,因此将使用Brain Storm(头脑风暴)的方式来描述需求:

·这是一个电商网站;

·这是一个O2O电商网站;

·这个网站有登录注册功能;

·这个网站有商品展示功能;

·这个网站有订单功能;

·这个网站有支付功能;

·这个网站有积分功能。

OK,需求就是这么多。估计很多小伙伴都已经开始吐槽了吧:上面的描述也能算需求吗?MOL可以很负责地告诉你,是的,而且这是沟通4个小时后的成果,你相信吗?好了,先不吐槽需求发起人了。上面的7个功能,就是我们这本书里要实现的需求。好像这也没什么难点啊。但如果你这样想就错了。至于哪里错了,MOL不会做直接回答,在后面的每个章节中,都会对这个问题进行回答,请大家自行品悟。如果你想要了解详细的需求,那可能要失望了,因为MOL并不打算在这里描述一个完整的需求,而且这并不是实际开发中的情况。在敏捷开发的项目里,一般都是到开发的最后阶段,才能明白客户想要的是什么东西。

这里引用一幅项目开发领域流传很广的漫画来说明,如图1-1所示。图1-1 项目开发漫画1.2 敏捷开发简介

前面提到了敏捷开发,听起来是一个非常“高大上”的名词。下面让我们来看一下敏捷开发的真面目。

敏捷开发以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备可视、可集成和可运行使用的特征。换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。(引自百度百科)

如果专业的解释看不太懂,没关系。我们用简单的语言来描述敏捷开发的过程。

小明想买一部手机,他告诉手机厂家:我想要一部手机,这部手机要好看、好用。

厂家收到需求以后,肯定是一头雾水,一定在想,我们做的每一部手机都非常好用呀,此时的心情是崩溃的。但是本着顾客是上帝的原则,厂家开始做这部好看且好用的手机。首先,他们把手机壳做了出来,打电话把小明叫到工厂:小明,手机壳做好了,你看是否符合你的需求?

小明看完以后,无非就两种回答,符合或不符合。如果符合,那么厂家将继续研发手机屏幕。如果不符合,那么将根据小明的需求继续修改。

又过了几天,厂家打电话:小明,屏幕做好了,你看是否符合你的需求?……

终于,在一个阳光明媚的下午,小明交完钱,拿到了自己心仪的手机,留下孤寂的厂家负责人在风中凌乱:就一个诺基亚1020,至于让我们这么费劲吗。

这就是一个敏捷开发的表现形式,它最明显的特点就是小迭代,每个小功能都去找客户确认,最后完成产品的同时,也就知道了客户的具体需求。

这样描述敏捷开发肯定是不全面的,我们的目的是不给出一个敏捷开发的准确定义,只是想让大家对敏捷开发有一个感性认识。

敏捷开发越来越多地被很多开发团体利用。它的好处就是开发周期短、与客户交流密切,一旦有问题出现,能很快做出响应。

在敏捷开发的团队里,逐渐地出现了一种人——“全栈工程师”,这种人的优势在于:他们是无所不知的。你说前端,他能给你讲HTML 5和CSS 3;你说C#,他能和你探讨.NET框架;你说Java,他能和你研究JVM;你说大数据,他还对Hadoop的理解有独到之处,仿佛是无所不能。相信很多摩丝都有一个“全栈梦”,加油!1.3 UI——用户界面

UI(User Interface,用户界面),这是一个可大可小的概念。往小了说,它就是一个图形界面,如网页、桌面窗口、手机窗口……只要是你看见的,都可以算是UI;往大了说,UI包括产品经理、用户体验工程师、美工(静态切图PS)、前端(HTML、CSS)、前端交互(JavaScript、jQuery、EasyUI)……

1.3.1 从UE说起

UE是一个容易让人产生歧意的缩写。经常写代码的人,尤其是写脚本语言(如PHP、Python)的程序员一定会说,UE是一个文本编辑器“Ultra Edit”;经常写需求的人一定会说,UE是用户体验“User Experience”。

这里所讲的UE是用户体验。那么用户体验是什么?先来摘录百度百科对它的解释:用户体验(User Experience,简称UX或UE)是一种纯主观的在用户使用一个产品(服务)的过程中建立起来的心理感受。由于它是纯主观的,因此就带有一定的不确定因素。个体差异也决定了每个用户的真实体验是无法通过其他途径来完全模拟或再现的。但是对于一个界定明确的用户群体来讲,其用户体验的共性是能够经由良好设计的实验来认识到的。随着计算机技术和互联网的发展,使技术创新形态正在发生转变,以用户为中心和以人为本的理念越来越被重视,用户体验也因此被称做创新2.0模式的精髓。

相信很多小伙伴都不愿意看这样长篇大论式的定义,那么我们用大白话来描述一下什么是UE。微信做得好,大家都愿意用它来社交;支付宝做得好,大家都愿意用它来支付;百度做得好,大家都愿意用它来搜索。当然,也有一些网站或项目做得就比较一般了,上线以后导致用户骂声连天。“做得好”和“做得一般”表明用户心里是有一杆秤的,这杆秤就用来衡量这些产品是否符合用户的需求和使用习惯。这杆“秤”就是用户体验。

一千个人眼里就会有一千个哈姆雷特,也就是说,任何一款产品,都不可能百分之百地满足任何用户。就像对于一朵菊花来说,有人觉得它芳香四溢,也有人觉得它臭,就是这个道理。

综述,一个产品,只要满足了大多数用户的需求,就是一个好的产品。

1.3.2 HTML 5&CSS 3

不得不说,HTML 5和CSS 3的发展正如日中天。HTML 5强大到可以完成手机APP的功能,如拍照、读取手机文件。CSS 3较之前面的版本,有更方便、更强大的渲染功能。当然,MOL并不是一个合格的前端工程师,所以这里对这些前端技术的描述只能点到为止。对于这些技术的运用,也不是后台程序员擅长的,我们更愿意把这些繁杂的前端工作交给专业的前端人员来做,因为他们一定比MOL有着更为专业的前端功底。

如果你的团队里正好没有前端人员,而你的BOSS又把前端的任务交给你了,怎么办?别着急,在后面的章节中,MOL会告诉你如何应对这些不合理的要求。

1.3.3 微信

相信各位小伙伴的手机上一定会装微信APP,微信以其极大的用户群体为基础,打造了一个互联网的社交平台。在这个平台上,有人“晒”幸福、有人吐槽春晚、有人发“鸡汤”、有人抢红包、有人卖面膜……当然,这些用法都有点Low了。对于我们这些Coder来说,更愿意看到自己做的东西挂在微信上面!本书中讲到的“川商卡”这个项目就是搭载在微信公众平台上面的。当然,你还可以开发微信公众服务号来展示自己的成果,这些都是后话。

之所以把微信公众号这个平台放在UI里面,是因为越来越多的电商网站愿意以手机为载体来实现用户流量的引入。如果商家自己去做推广的话,将是一笔不小的开支,所以商家更愿意使用已成型的平台来推广自己的产品,而微信公众号无疑是一个不错的选择。比如我们用的信用卡公众号,或者订阅了某个公众号,这些都属于微信推广的一种手段。微信作为一个平台,有一套自己的规范,也就限制了网站的展现形式,所以从这个角度来说,微信也算是UI的一份子。1.4 数据库

别问我数据库是什么。MOL说过,这本书里不讲基础知识。在这里讲的是如何去设计数据库。

MOL相信很多大学老师一定是这样教学的:设计数据库一定要先设计数据字典,这个字典看起来像这样,如表1-1所示。表1-1 登录信息的数据字典

这个字典描述了一个用户登录信息表。设计好这个字典以后,再去数据库(SQLServer\Oracle\MySQL……)中去实现这个字典,实现的方法无非就是SQL语句create table,或者用图形化工具去设计表。

大家有没有觉得这个字典设计得有点鸡肋?如果要改需求,比如加入注册时间这个字段,试问,你会先修改字典,然后再去修改数据库吗?如果需求更改得比较频繁,那么你一定会厌烦“数据字典”这个东西的。

其实不然,数据字典是一个神器,只是你的打开方式不对。

1.4.1 PowerDesigner设计工具

面向对象是本书的一条主线,本书中对面向对象的表述甚至有些“极端”,但是一定可以把OO(面向对象)思想灌输给大家的。

面向对象里说,一切皆对象。也就是说,数据库是对象,数据库中的表也是对象。因此,我们将以对象的形式来描述一个数据库表,这个描述将以用户登录信息来举例。

在数据库里,对“对象”的体现莫过于“属性”,属性是什么?说白了,属性就是字段。怎么理解?一个登录对象,必然有用户名和密码,这是它的属性。那么反映到数据库中,就是用户名字段和密码字段,这样就理解了吧。

为了让一个数据字典看起来更像是一个对象,我们将借助PowerDesigner(以下简称PD)工具来设计。如果不会用PD,请自行去“某度”或“某狗”去搜索一下。

下面先来做一个概念模型CDM(Concept Data Model),如图1-2所示。

这样看是不是有点对象的意思了?有对象名,有对象属性。

那为什么建立的是CDM而不是物理模型PDM(Physical Data Model)?先不着急来回答这个问题,先把建立的CDM生成PDM,然后进行对比。生成的PDM如图1-3所示。图1-2 登录信息的概念模型图1-3 登录信息的物理模型

看起来二者好像没什么区别,那么下面再建立一个用户订单的对象。我们知道,一个用户可以有0个或多个订单,那么用户&订单的CDM看起来像下面这样,如图1-4所示。

它生成的PDM如图1-5所示。

到这一步,就看出二者的区别了吧。PDM的描述更接近于数据库,因为可以从PDM中清晰地看到关于外键等数据库表的描述;而CDM更接近于需求,我们只需要关心一个用户有多个订单就可以了,至于外键之类,不是CDM要关心的问题。

在设计数据库的时候,一定是从需求出发,所以设计CDM会更贴近需求,也会更容易一些。图1-4 多表间关系的概念模型图1-5 多表间关系物理模型

OK,我们再回到数据字典的问题,为什么要用PD来画一个CDM,而不是用Excel之类的软件来做一个数据字典的表格?用PD做数据库设计的好处有很多,这里只列举两点:

·便于管理。当有很多项目的数据库需要管理的时候,可以很轻松地从PD里面找到想要维护的表。

·便于生成数据库。我们建立的CDM可以生成PDM,PDM又可以生成数据库脚本,这些脚本是可以直接在数据库中执行的。当然,如果为PD设置了ODBC(Open Database Connectivity)连接,则可以直接在PD里通过操作数据库来生成表。

以上两点好处,足以让我们选择PD来设计和维护数据库了。

1.4.2 关于SQL语句

相信很多新手程序员都喜欢用大量的SQL语句来实现一个又一个复杂的功能,而且非常有成就感。但本书不会教你怎样写SQL语句,而且会劝大家尽量少写SQL语句。为什么呢?很简单,我们要面向对象!一个复杂的SQL语句是很难体现对象特性的。那么如何保证尽量少地去写SQL语句呢?这是第3章的内容,这里先不做介绍。

少写SQL语句,并不是不写SQL语句。那么哪些地方需要写SQL呢?答案是存储过程、事务、触发器。可以看出来,这里列举了存储过程、事务、触发器这3种SQL语句的出现形式,它们有一个共同点,就是业务规则是相对固定的。比如,新用户注册完成以后,数据库要悄悄地给这个用户添加一个购物车,这种业务场景最好使用触发器。关于触发器的优势,这里也不会细说,MOL只会轻轻地告诉你,触发器比你写代码提交快很多。

既然项目中出现了SQL语句,那么就需要对这些SQL语句进行分析,看它们的执行效率是否符合要求。比如一个select语句要执行10分钟,那么这个SQL语句就得“枪毙”重写了。通常,看一个SQL语句的执行效率,主要集中在全表扫描和索引上面,尽量不使用全表扫描,尽量使用索引,目的都是让SQL执行起来更快一些。

关于数据库,要说的最后一点是主键的问题。主键的类型有多种多样,可以使用数字、字母、时间等,只要保证它是唯一的就可以了。那么我们到底应该取用什么类型呢?一些专家一定会说:看情况而定。MOL当然不会这么说。建议大家使用GUID类型。使用GUID类型的好处就是:它的长度是固定的,而且永远都不会重复。如果使用int类型,虽然可以很轻松地使用主键自增保证它是唯一的,但当它增长到一定数量的时候,int已经不足以描述了。

MOL曾经经历过一件事,彩票奖池金额在2016年元月的时候已经到达2.4亿多,这个数字是无法用int来描述的,所以把程序中所有用int描述主键的地方都改成了long。其他的数据类型都有自己的缺陷,所以使用GUID来作为主键字段的数据类型。当然,GUID也有自己的缺陷,如不直观、没有数据含义等。但这些功能其实都可以解决和避免,所以为了简单和实用,我们使用GUID作为主键字段的数据类型。可以看到,MOL说建议GUID这件事情时说了3遍,正所谓重要的事情说3遍嘛。

前端和数据库都描述完了,最重要的代码就要登场了,你以为代码就是一堆C#关键词的集合?我就只能“呵呵”了。

那么我们应该如何去组织代码呢?面对频繁的数据库操作,要如何尽量少地写SQL语句呢(在本书的项目中,C#代码中是不掺杂任何SQL语句的)?大量的SQL查询是否会影响网站速度?……

这些疑问,将在后面的章节中一一解答。第2章 为什么是三层

还记得在引言中提到的几位主人公吗?从这一章开始,他们就要粉墨登场了!“三层架构”这个词一定是新手程序员经常听到的,大家听起来一定觉得它有点“高大上”的感觉,然后纷纷把自己的项目进行分层,以求变成三层。那么,三层架构到底是什么?为什么要分三层?我们慢慢说来。2.1 MOL带兄弟们去吃饭

时维九月,岁属三秋,这是一个阳光明媚的金秋,MOL所在的公司又新招了三位同学,MOL总算不是孤军奋战了,于是MOL带大家去了楼下一家餐厅吃饭。吃饭不是目的,这是给大家上的第一堂课。

到了餐厅以后,一个很水灵的妹子迎上前来,问道:“几位帅哥要饭吗?”

MOL当时就不高兴了,回道:“你看我们长得像丐帮的吗?”

妹子脸一红:“我的意思是,各位想吃点什么?”

这时,月月搭腔了:“蒸羊羔、蒸熊掌、蒸鹿尾儿、烧花鸭、烧……”

妹子赶紧打住:“哥哥,我得问一下厨房师傅,看看能不能做。”

不大一会儿,妹子出来了:“实在对不住,您几位刚才点的那些,我们这里都做不了,因为这里是西餐厅。”

月月:“那二尺长的龙虾有吗?”

妹子:“二尺长的没有,有二尺七的,要吗?”

MOL一看不对劲,这是要把我吃到破产的节奏啊,赶紧说:“二尺长的龙虾都没有,那就来小龙虾吧。”

妹子:“小龙虾暂时没有,如果您可以等的话,等采购师傅回来了,就有了。”

MOL:“可以等,不就几分钟嘛。”

妹子愤愤地下去了,月月也一脸不满意,MOL赶紧打圆场:“不就是龙虾嘛,大小都是龙虾,小怎么啦?小就不能满足你了?”

然后是等待吃饭……

吃完饭回到公司,MOL招集大家开会。

MOL:“今天这顿饭不能白吃,它将开始我给你们的第一课——三层架构。”

月月:“吃饭都能扯上架构,神了嘿。”

鹏辉:“今天的饭吃得确实有点意思,不过还能和程序扯上关系就有点意思了。”

MOL:“我们刚才在餐厅吃饭的时候,总共有这么4个角色,分别是我们3个“饭桶”、服务员、大厨和采购师傅。”(下面都是MOL口述,将不再以引号来包含)

在程序员的世界里,这几个角色分别对应的关系是:

·我们3个“饭桶”对应用户,因为我们是花钱享受服务的。

·服务员是UI(User Interface用户接口)层,她是要展示给用户,并且和用户进行交互的,而且她还要和大厨进行交互。

·大厨是BLL(Business Logic Layer业务逻辑层),他的任务是把食材加工成美食,并交给服务员,所以他既要和采购师傅交互,又要和服务员交互。

·采购师傅是DAL(Data Access Layer数据访问层),它的任务是把食材采购回来并交给大厨。

除此之外,还有一个隐形的角色是菜市场的大妈,她负责把菜卖给采购师傅。她对应我们软件系统中的数据库。当然,我们对大妈是不感兴趣的,所以这里先不说大妈的事。

OK,根据上面的描述,我们可以把一个餐厅里的工作分成3个部分,分别是服务员、大厨和采购师傅,他们之间的相互关系如图2-1所示。图2-1 餐厅分工

大家有没有想过,如果我雇佣一个人,这个人既会炒菜又能采购,还会当服务员,那么这些角色不就不用分开了吗?

非常好,我们假设有这样一个人存在,他既要当服务员与食客沟通,还要炒菜,还要去买菜,那么将会发生什么情况呢?

这个人先要恭敬地问食客“您来点什么?”,然后再跑到厨房换上工作服开始炒菜,如果发现没菜了还得自己去买菜。我相信,即使有这样一个人存在,那么他也会累得够呛。而且他炒菜或者采购的时候,是不能与其他的食客沟通的。最后他累得实在不行了,辞职走人了,老板就哭了,因为他一走,餐厅就没人干活了,餐厅也得关门。

所以,分开服务员、大厨、采购员这几个角色,有利于每个角色都专注于自己的职责任务,而且,即使有人搁挑子不干了,那也只需要找一个对应职责的工人来顶上就可以了,不至于让整个餐厅都变得很被动。

好了,说完了餐厅的分工,再来说一下我们所关心的代码中的三层架构。

通常意义上来说,三层架构是UI、BLL、DAL这3层。这3层可以对应到餐厅中的3个角色来对比理解。UI层负责与用户交互,并将用户的请求交给BLL层处理;BLL层负责从UI层获取请求并将处理后的数据交给UI层,同时它还向DAL层发送请求,并获取DAL层返回的数据;DAL层负责接收BLL层的请求,并进行数据处理然后返回给BLL层,在大多数情况下,DAL还需要从数据库中获取数据。它们之间的关系如图2-2所示。图2-2 程序中的三层结构

同样的,我们完全可以不使用三层结构就可以完成一个项目,这种代码结构最常见于新手程序员写的代码。这样的结构将会面临很大的风险,如果业务逻辑变动,那么将会出现“牵一发而动全身”的现象,由此不得不对整个项目进行修改。所以,分层可以让专业的层(Layer)去做专业的事情,如果逻辑有变动,那么只需要修改相应的层就可以了。

PS:餐厅吃饭的例子非常经典,它将贯穿于本书中的章节,在后面的章节中经常会说到“如果餐厅中的大厨有个助手……”,希望大家能立刻回想起MOL在这一节给大家讲的餐厅吃饭的例子。2.2 动手写一个三层结构

说了这么多,都只是停留在概念的层次,接下来,我们要写一个简单的三层结构的框架。这个框架只需要实现一个功能:用户输入两个数,并选择运算方法,运算只包括+、-、*、/。程序通过计算,将计算结果输出到用户界面上。

OK,需求已经非常明确了,就是要做一个简单的能进行加、减、乘、除运算的计算器。那么前端可以使用任何方式,比如控制台、WinForm、WebForm、MVC……为了直观和简单,这里将采用WebForm来做为前台界面。而BLL主要是将数据逻辑进行处理,并调用DAL层计算结果,将得到的结果返回给界面。DAL只需要提供数据就OK了。在本例中,不考虑边界异常(如太长的数字会溢出等情况)。

首先需要把项目的框架搭建好。新建一个名为Mol.Calc的解决方案,并加入一个Web项目(Mol.Calc.Portal)和两个类库项目(Mol.Calc.Bll和Mol.Calc.Dal),如图2-3所示。图2-3 三层代码框架

PS:项目的命名一定要规范,一般来说,项目命名都是“公司.项目.模块名”。MOL所使用的开发环境是Windows 7+Visual Studio 2015+SQL Server 2012。关于环境的配置这里不会多说,否则显得本书很low,大家也会很不耐烦。

2.2.1 DAL层的实现

有了项目框架以后,就可以写代码了。首先需要一个处理数据的功能,这个功能大家一定要记住,和数据打交道的功能,最好放在DAL里。

在本例中,DAL层只需要处理加、减、乘、除4种运算就可以了。所以我们分别写4个函数来实现这4种运算,如图2-4所示。图2-4 四则运算的实现

在本例中,加、减、乘、除这4种运算确实是太简单了,用它来占用一层有点浪费,不过在大项目中,这样写是非常有必要的。

2.2.2 BLL层的实现

接下来要实现BLL层。BLL层是三层里最难学的一层,因为大部分的BLL中的代码都是这样的://实例化一个DAL 对象operate dal=new Mol.Calc.Dal.operate();//调用DAL 计算加法1+2dal.Add(1,2);

这样的代码看起来毫无生气,甚至没有存在的意义,因为DAL层就可以把计算做完了,为什么还要硬生生地加一个BLL层呢?

大家一定要记住,我们不是为了分层而分层,而是为了实现高效可维护的代码结构。

BLL层的作用是要处理业务逻辑,所谓的业务逻辑就是要判断UI层传入的数据应该如何排列组合提交给DAL层,如果有不合法的数据,就要及时中断,不向DAL层提交。

本例中,需要判断用户选择的是哪种运算,并去调用DAL层中相应的运算;除此之外,还要判断:当用户要计算除法时,用户输入的除数是否为0。

BLL层的代码如图2-5所示。图2-5 BLL层代码

注意:其实除数不能为0这样的验证应该放到前台UI层去验证,这里把它放到BLL层里,是为了强化大家对BLL层的理解。

2.2.3 UI层的实现

前面的2.21节和2.22节,我们实现了数据的获取和处理。接下来就要写前台UI的代码了。UI代码比较简单,就是新建一个WebForm页面,名称为Calc.aspx,并在这个WebForm页面中加入两个文本框、一个下拉列表框(设置下拉列表框选项为+、-、*、/)、一个按钮、和一个显示计算结果的Label。UI后台,只需要实例化一个BLL层对象,并调用BLL层的方法既可。前台界面如图2-6所示。图2-6 UI界面

UI后台的代码如图2-7所示。图2-7 UI后台代码

这样,一个简单的三层代码结构的示例就完成了,运行结果如图2-8所示。图2-8 程序运行结果2.3 简说MVC

提到三层架构,很多人就会想到MVC(Model View Controller,模型-视图-控制器)模型。MVC的结构如图2-9所示。图2-9 MVC模型示意图

图2-9描述了一个MVC框架处理用户请求的流程。(1)用户发起请求,请求将被送给Controller。(2)Controller去Model中取数据。(3)Model返回数据给Controller。(4)Controller将数据返回给View。(5)View展示给用户。

如果这个流程让你觉得难以理解,不要担心,因为我们还没有开始写MVC的代码,所以我们无法理解用户请求为什么是到控制器(Controller)而不是到视图界面(View),最后返回的时候不通过控制器返回,而通过视图来返回……大家只需要对MVC有一个感性认识即可,知道每一部分是干什么用的就OK了。

2.3.1 纠正一下老师的说法

很多老师在讲到MVC的时候,都会和三层架构进行对比,并且会给出下面一幅图(如图2-10所示)。图2-10 很多老师都会这样画

老师画完这个图以后,告诉大家:MVC中的View和Controller相当于三层架构中的UI层。而MVC中的Model相当于三层架构中的BLL。

每当听到这样的解释时,MOL特别想问问老师:你把DAL层吃了?当然,这样的做法有点激进。但是,老师这样的讲法肯定是不对的。三层架构是一种思维,MVC是另一种思维,如果非要把二者放在一起对比的话,难免牵强。

接下来,我们来写一个MVC的程序,看看MVC到底是什么样子的。

2.3.2 MVC的第一个程序

前面提到过,MVC只是一种设计思想和程序框架,那么,也就是说MVC并不是.NET特有的,其他语言也有自己的MVC实现,我们在真实项目中使用的,其实也不是真正的MVC。但是第一个MVC程序一定要简单,所以我们使用微软提供的MVC来做。

微软在.NET 3.5以后的版本都支持MVC,这里使用的是.NET 4.5版本下面的MVC 4。好了,下面来新建一个Web项目,如图2-11所示。图2-11 新建Web项目

如果读者以前用的是Visual Studio 2010,那么这个界面可能不太习惯。从Visual Studio 2012开始,WebForm、MVC、Web API等这样的Web项目都变成了一个“ASP.NET Web应用程序”,选择这个应用程序以后,单击“确定”按钮,进入选择项目类型步骤,如图2-12所示。图2-12 选择Web类型

在这一步中选择MVC项目,然后单击“确定”按钮,进入项目解决方案的管理界面,如图2-13所示。图2-13 MVC代码界面

可以看到,在图2-13中,用标注框所标出来的地方就是我们前面所提到的Model、View、Controller。

打开HomeController.cs,修改Index方法为下面的代码:public ActionResult Index(){ string msg = string.Format(@"这世界,我来了!"); ViewBag.Message = msg; return View();}

然后修改对应的Index.cshtml为下面的代码:

@ViewBag.Message

直接运行代码后会发现,我们写的文字已经显示在页面上了。页面效果如图2-14所示。图2-14 第一个MVC程序页面效果

运行程序以后会发现,URL只是localhost:端口号,而没有实质的页面路径。我们把URL补全为localhost:端口号/home/index,还能看到相同的效果。通过这个简单的程序可以看到,用户(这里是浏览器)是向控制器(Controller)中的Action(这里是Index)发起请求,Action会进行数据处理(本例中是给ViewBag.Message赋值),然后返回给View(视图),View接收到返回数据以后,将数据显示到页面上,最后就可以通过浏览器看到效果了。

这段话里埋下了太多没有讲解的知识点。(1)为什么localhost:端口号==localhost:端口号/home/index

打开App_Start下面的路由配置文件RouteConfig.cs,如图2-15所示。图2-15 路由配置文件

可以看到这个文件中配置了一个叫Routes.MapRoute的对象。这个对象有一个默认属性defalts,表示当URL中没有控制器和Action的时候,指向哪个控制器下的Action。在本例中,它指向的是home/index。当然,这个默认设置是可以修改的。(2)ViewBag是什么

在Index这个Action中使用了ViewBag对象,它是一个数据传递的载体,只需要为这个对象的属性赋值,前台就可以取到了,ViewBag的属性是不需要提前定义的,例如,要给ViewBag.Mol赋值为“帅”,那么前台就可以通过ViewBag.Mol来获取到“帅”。是不是很神奇?

除了ViewBag,还有一个叫ViewData的对象也可以完成类似的操作。它的用法是:ViewData["Mol"]="帅";

关于ViewBag和ViewData的区别,这里不做详述,大家需要自行去学习。(3)Model跑哪里去了

Model呢?前面用到了控制器和视图,单单把Model落下了。Model是一个实体集合,可以定义任何实体类。这个实体类可以是用户类,可以是订单类……可以把Model理解为这样一种东西:它是一种载体,通过这种载体,可以以面向对象的思维去处理数据。例如,定义一个User类,那么在控制器中就可以实例化一个User类,然后传给视图去展示。伪代码如下:User user=new User();user.name="Mol";user.gender="male";ViewBag.Person=user;

如果大家还不太了解MVC,那么就找一些资料学习一下。本书的重点不是MVC,所以这里只是略带一说。

2.3.3 为什么要用MVC之我见

其实MVC与传统WebForm的区别还是很多的,但是很多不同点还不足以引起大家使用MVC的欲望。这里只说几点大家可能会关注的地方。

·WebForm更容易上手,也就意味着程序员会忽略更多的细节。比如一个按钮是如何被解析成input标签的。这样的编程方式其实不利于对程序的理解。

·WebForm中设计了“生命周期”的模式,从页面出生到消亡,会经历很多个状态,比如常见的Page_Load就是其中的一个状态。这样多的生命周期,其实并不利于新手理解程序是如何处理请求的。

·WebForm页面中会保存大量的ViewState,这样就可以记住“之前”(事件触发前)的状态。这些ViewState会对优化工作造成不小的困扰,而且经常在程序员不注意的时候,页面就会狂飙到好几兆的大小。

如果你用过WebForm,也用过MVC,那么一定会觉得MVC是非常纯净的,因为它的流程透明,页面干净,不会生成意想不到的ViewState。

·WebForm中的页面都是继承自System.Web.Page类。而Page类是不可以实例化的,那么这种现象就会对单元测试造成很大的困难,有些程序员甚至直接跳过了单元测试。而在MVC中,所有的请求将会被汇集到Controller类中,而对控制器和其中的Action做单元测试是比较容易的。

·WebForm中的前台是aspx页面,也就是说这个前台页面并不是一个纯净的HTML页面。当程序员从美工手中接过静态页面的设计以后,需要把大量的input标签转换成按钮、单元框、文本框……这个枯燥的工作一定会把人逼疯的。

·这一点其实算是个彩蛋,因为并不能算是一个非常直接的原因。把项目提交到Git上以后,Git平台中的“代码分析”功能会检查整个项目的代码完整性、可读性、规范性等。其中,规范性要求代码需要按照一定的命名规则来书写,而如果项目使用了WebForm,那么Page_Load这样的函数名就一定会被检查出来,并且还没有办法把它改成其他的函数名,这是多么的“坑爹”。

其他的区别还有很多,但以上所列几点已经有足够的理由让我们去使用MVC。

在本章中,我们将使用微软提供的MVC来做示例。在前面的内容中提到过,MVC只是一种编程思想,而不是某个公司或机构的专有技术,在后面的章节中,我们会引入Spring.NET中的MVC。2.4 向三层代码中加入面向对象

面向对象其实是一个非常宽泛的概念,宽泛到不足以用一个章节甚至是一本书来说明面向对象,但MOL将尽量在书中的例子中浸透面向对象的思维。

前面已经讲述了通常的三层代码结构,本节将在三层代码中加入面向对象的元素。这种面向对象的思想在本节中将体现在两个地方:

·数据库表的面向对象;

·将所有的SQL操作都放到一个类(SqlHelper)中。

2.4.1 实例化数据库表

通常意义上,从数据库中获取数据,一般都需要按照ADO.NET的步骤来写,ADO.NET的代码如下:///

/// 获取所有的订单信息 /// /// public DataSet GetOrder() { string connectionString = @"Data Source=.;Initial Catalog= ReportServer;User ID=sa;Password=000"; DataSet re = new DataSet(); using (SqlConnection con = new SqlConnection(connectionString)) { string sql = @"select userid,username from users"; SqlDataAdapter ada = new SqlDataAdapter(sql, con); ada.Fill(re); } return re; }

获取到数据源以后,需要在BLL层进行数据装配。BLL层代码比较简单,只是简单调用DAL层返回数据,BLL层代码如下:public class OrderBll { ///

/// 调用DAL获取数据 /// /// public DataSet GetOrder() { OrderDal dal = new OrderDal(); return dal.GetOrder(); } }

然后再以DataSet的形式返回到前台,前台在展示的时候,就需要按照DataSet的格式来展示。比如,展示userid字段,那么就需要这样写:

展示效果如图2-16所示。图2-16 获取数据展示效果

通过上面的代码可以发现,DataSet这个类将贯穿于DAL-BLL-UI这三层之间。而DataSet类是一个与数据库打交道的类,这样就导致我们不管在哪一层(Layer)都需要知道这个数据集(DataSet)里的结构,包括这个数据集中有几个表,每个表中包含哪些字段等。

当操作的表达到几十个的时候,用DataSet操作数据已经变得非

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载