架构之路(五):忘记数据库

前面写了这么多,很大程度上就是为了这一章做准备。面向对象或者领域驱动,最重要的一点就是要忘记数据库!我花了很长很长的时间,才理解了这一点,从而真正的迈向一个崭新的天地;而后,我又花了很长很长的时间,才勉强做到这一点;我希望,有一天,这将不再是一个问题,我不需要考虑这一点……

为什么业务层这么薄

三层架构流行起来之后,我们很清楚的知道UI层负责页面交互并调用下一层,也知道DAL层就是和数据库打交道。但BLL层?什么才算是“业务逻辑”?有各种各样的解释,但这些不都是sql做的么?对于绝大多数的应用系统而言,除了对数据库进行“增删改查”以外,实在不知道还能做些什么?更何况,不是还有超级强大的存储过程么!

所以,很多系统,即使勉强弄出一个业务层,也“薄”得不像话,像一层塑料薄膜一样,让人有一种把它立即撕掉的强烈的冲动。

为什么?

这得从.NET阵营从历史说起。.NET阵营的同学知道三层架构,多半是从PetShop开始,这被奉为三层架构的经典,很多项目甚至是直接复制其架构。在当时,它是一种了不起的进步。那时候,还是从ASP向ASP.NET转型的过程,很多asp项目,sql代码都还是写在html里面的!所以,UI和DAL的分离,无疑具有明细的示范效应。

但微软的步子,不大不小,刚好扯着蛋。

步子小一点,做成两层架构,估计一点问题都没有,大家都能接受;步子再大一点,就得上ORM,可惜微软当时还没条件支持。所以就搞出了这么个不明不白稀里糊涂的概念出来,折磨了我好久好久……

长期以来,.NET的阵营,在应用级层面,其实是“面向数据库”的。从DataSet、DataGrid、DataSourceBinder之类的,都可以看出来。即使是Entity Framework,最开始也是从数据库的表向.NET的类进行映射。这些,都极大的制约了.NET阵营同学面向对象的思维拓展。

好在我终于跳出来了。

面向数据库

为了说明,我们举一个最简单的例子。

需求是:记录文章(Article)的浏览数(ViewCount)。每当文章被阅读(View)一次,浏览数加一。

看到这个需求,你首先想到的是什么?是不是:

Update Article set ViewCount = ViewCount + 1;

如果是这样的话,恭喜你,你还牢牢的守住了“面向数据库”的阵地。

/*

面向数据库并不是不可接受的,面向对象也并不一定比面向数据库“高级”。
这只是两条道路的选择,如果你愿意看一看另外一条路的风景,就请继续;否则,就此打住吧。

*/

面向对象

那么,面向对象或者领域驱动应该是怎么做的呢?

        public void View()
        {
            //从数据库中取出Article
            Article article = session.Load<Article>(articleId);

            //改变Article的ViewCount属性
            article.ViewCount += 1;

            //将改变后的Article再存入数据库
            session.Save(article);
        }

有什么感觉?眼前一亮,还是不可思议?想得更深一点的,是不是觉得这是多此一举,一句sql就能解决的问题,搞得这么复杂?

我当年,考虑最多的,最不能接受的,是性能问题。

  1. 这必须利用ORM,即使不考虑ORM生成的sql高不高效,就这生成sql的开销,应该就不低吧?
  2. 这样做,取数据,打开一次数据库连接;存数据,又打开一次数据库连接。就算有连接池,但能省一点就省一点不是更好?

所以,如果你也和我一样,倒回去看我之前的博客吧!

这样做,还有其他很多具体的技术问题,我们后续博客会逐一展开说明。

为什么

我们还是回到大方向上来,为什么要这么做?换言之,“面向数据库”有什么问题,或者说“面向对象”有什么好处?

我觉得,“抽象”、“解耦”、“复用”之类的说法,都还没有触及根本。最根本的原因,还在于我们的大脑,我们的大脑不适应于把这个世界抽象成一张一张的表,而更适应于一个一个的对象。随着系统日趋复杂,这种现象就表现得越明显。

我曾经参与过一个项目,它的数据库结构打印出来,得用地图那么大一张纸(我不知道算A几了),密密麻麻的全是表,各种线条交错其中,我看着就头皮发麻。部门里面像个宝贝一样把这张表供着,因为公司没法打印也没法复印啊!(我不知道他们最开始是怎么得来的,估计肯定麻烦)

如果你一边读一边在想,就会发现,“不对呀,有多少表就有多少类,类图不是一样复杂吗?”

是的,而且由于抽象,类很可能比表还要多。但是,有于抽象,在我们进行架构、设计、沟通的时候,可以暂时的抛弃很多细节。比如,我们可以说,“文章被评论之后,文章作者的积分加10分”,这个时候,我们就不考虑文章有很多种:博客、新闻、问答、评论……,也不考虑积分增加是直接改积分总分呢,还是添加一条积分记录,或者还要同步……。如果只有表,你怎么说?

当然,表的结构也可以设计成类似于继承的样子(类的继承关系也最终会映射成表结构),但是,在交流沟通中,你如何表明这种抽象关系呢?更重要的是,软件工程中常用的一个概念:委托。

单纯从程序的角度上说,使用ORM,面向对象,还增加了系统的复杂性。毕竟多了一道工作,而且把对象映射到数据库不是一件简单的工作,尤其是你还要考虑性能问题的时候。

那为什么我们还要这样做?委托,换言之,把复杂性往其他地方推。我记得我反复讲过这一点,架构的一个重要工作,就是把复杂性进行拆分和推诿。拆分估计大家好理解,但“推诿”是个什么意思,推给谁呢?管它呢,我只做我分类的事,其他的,UI推给BLL,BLL推给DAL,DAL推给DBA,DBA推给采购部……

写在这里很搞笑,但事实就是这样的。在性能篇,我说,你要写高性能的代码,你就是抢了人家的饭碗,就这个意思。UI都把DBA的活儿干了,人家吃什么?你代码都写成01001010101010二进制了,别说做汇编的,估计做CPU的都活不下去了。

我们这里,就是把复杂度推给了Map团队、ORM工具开发商和DBA。

因为我们要和客户谈需求啊,典型的是领域驱动,要和客户/领域专家找到“共同的语言”,这共同的语言是什么?是表结构?估计如果开发的是一个财务会计系统,这还是可行的——估计早期的系统大多就是财务报表类系统?说不定还真是这样。为什么面向对象从Java开始流行,Java是虚拟机,可以用在微波炉报警器之类上面的,底层数据结构可以完全脱离数据库啊!.NET做什么起家的,就报表啊!呵呵。

总之,发展到今天,随着系统复杂性的增加。在系统的架构设计中,我们不得不将现实世界首先映射成一个一个可以封装、具有继承多态特性的对象,并且将重心放在这些对象关系功能的维护上。

数据库?就先不管它吧。

只有脱离了数据库的束缚,我们才能自由的翱翔在面向对象的世界里!

忘不掉

“问题是我忘不掉啊!”

“我只要看到需求,脑子里马上就是数据库就是表。”

“没有数据库,我都不知道怎么开始写代码了。”

……

是的,忘掉数据库是很难很难——尤其是对于我们这些老人来说。已经浸淫sql数十年的高手,你让我忘掉它?你以为写小说啊,张无忌学太极啊?

我只能说说我是怎么做到的,希望能给你一些参考。

我就假设我的系统不是用“关系数据库”存储数据,不是mysql,不是oracle;我用nosql,我用xml文件存储,行不行?nosql,怎么用?不知道啊,我十窍通了九窍。但我就要在我还不知道nosql怎么用的时候,就开始构建我的BLL/领域层。而且我只设定一个最简单的假设:

  • 所有的对象都可以直接从硬盘Load()出来
  • 所有的对象都可以直接Save()到硬盘
  • 对象之间用1:1、1:n、n:n建立关联即可

究竟怎么从硬盘里存取(所谓的“持久化”),以后再说。我连用什么进行持久化都不知道,现在怎么考虑?但有一条,反正不会用关系数据库,估计是用nosql吧……

最终的期望

真正的对象数据库!快出来啊,求你了……

惯例说我的项目进展:
1、写文档写到吐……
2、重构累成了狗……
本计划发布了新版本再写这篇博客的,但实在不能再拖了。博客系列接下来,就进入项目的具体开发了,代码还乱成一堆,啊……

时间: 2024-12-14 08:10:50

架构之路(五):忘记数据库的相关文章

架构之路(九)Session Per Request

前面的两篇反应很差:没评论没赞.很伤心啊,为什么呢?搞得我好长一段时间都没更新了——呵呵,好吧,我承认,这只是我的借口.不过,还是希望大家多给反馈.没有反馈,我就只能猜了:前面两篇是不是写得太“粗”了一点?所以这一篇我们尽量详细点吧. Session Per Request是什么 这是一个使用NHibernate构建Web项目惯用的模式,相关的文章其实很多.我尽量用我的语言(意思是大白话,但可能不精确)来做一个简单的解释. 首先,你得明白什么是session.这不是ASP.NET里面的那个ses

忘记数据库

忘记数据库 前面写了这么多,很大程度上就是为了这一章做准备.面向对象或者领域驱动,最重要的一点就是要忘记数据库!我花了很长很长的时间,才理解了这一点,从而真正的迈向一个崭新的天地:而后,我又花了很长很长的时间,才勉强做到这一点:我希望,有一天,这将不再是一个问题,我不需要考虑这一点…… 为什么业务层这么薄 三层架构流行起来之后,我们很清楚的知道UI层负责页面交互并调用下一层,也知道DAL层就是和数据库打交道.但BLL层?什么才算是“业务逻辑”?有各种各样的解释,但这些不都是sql做的么?对于绝大

架构之路:nginx与IIS服务器搭建集群实现负载均衡(三)

参考网址:https://blog.csdn.net/zhanghan18333611647/article/details/50811980 [前言] 在<架构之路:nginx与IIS服务器搭建集群实现负载均衡(二)>中提到有好多有趣的地方,接下来就为大家一块儿讲讲在深入研究过程中遇到那些有趣的事情. ·实战之行--发现问题 ·探索之旅--寻出问题原因 ·解决之道--解决问题 [实战之行] 在<架构之路:nginx与IIS服务器搭建集群实现负载均衡(二)>中做了小Demo,当时做

我的VSTO之路(五):Outlook初步开发之联系人扩展

原文:我的VSTO之路(五):Outlook初步开发之联系人扩展 上一讲我们完成对Word的介绍,文本开始,我将着重介绍Outlook.Outlook是微软Office中一个非常实用的工具,尤其在一个拥有Windows Domain的公司局域网中,Outlook是员工最常用的通讯工具,所以对Outlook实行进一步的定制开发的需求量是很大的.本文中,我先以联系人的扩展为开始,讲解如何开发一个强大的Outlook插件. 故事的开始 首先我们假设一个场景.有一天,市场部的同事来找你帮个小忙(有经验的

基于Extjs的web表单设计器 第五节——数据库设计

这里列出表单设计器系列的内容,6.7.8节的内容应该在春节后才有时间出了.因为这周末就请假回老家了,准备我的结婚大事.在此提前祝大家春节快乐! 基于Extjs的web表单设计器 基于Extjs的web表单设计器 第一节 基于Extjs的web表单设计器 第二节——表单控件设计 基于Extjs的web表单设计器 第三节——控件拖放 基于Extjs的web表单设计器 第四节——控件拖放 基于Extjs的web表单设计器 第五节——数据库设计 基于Extjs的web表单设计器 第六节——界面框架设计

架构之路

架构之路 www.ediandian.org 我,是一个Linux运维工程师,俗称运维亦或黑锅侠,英文:OperationEnginner;网名:沐浴春风,别名:浴春风,英文名:fonge;祖籍河南周口市,现工作于杭州;做事风格,来去如风,有始有终:性格热情豪爽,奔放而不羁,勇而有义,宽宏而有大略:表达能力-5;年龄,80的尾巴,关注技术和运动,喜爱数码产品,对于这些东西我只能说:买买买,按斤买;我会犯错误,偶尔有点坏脾气但不会任性而为,技术面前一颗敬畏和征服之心;技术人,充满创造力的自由不羁的

云路五年 未来正来

阿里云五岁了. 五年很短,我们畅想中的云图还远未到来:五年又很长,中国云计算从零开始,如今深入泥土里的根系,已经足以支撑一颗参天大树. 从2009年9月10日 阿里云计算有限公司成立的那一天开始,中国云计算已不再只是一颗梦想的种子,有这么一群心怀理想的人开始为它默默耕耘.在这条漫漫长路上,每走一步都伴随着无数的汗水,但我们每一步都走得很坚实. 2011年7月8日 阿里云官网www.aliyun.com上线,从此,阿里云自主研发的“飞天”平台开始以公共云计算服务的方式对外提供商业服务. 在大规模的

Oracle笔记(十五) 数据库备份

Oracle笔记(十五) 数据库备份 数据库的备份操作是在整个项目运行中最重要的工作之一. 一.数据的导出和导入 数据的导出和导入是针对于一个用户的备份操作,可以按照如下的方式完成: 1.  数据的导出 在硬盘上建立一个文件夹:c:\backup: 输入exp指令: 输入用户名和密码: 设置导出文件的名称:导出文件: EXPDAT.DMP: 2.  数据的导入 先将表删除干净: 进入到导出文件所在的文件夹之中:c:\backup: 输入imp指令: 输入用户名和密码: 导入整个导出文件 (yes

西二旗程序员家庭装修的架构之路 - 1

在北京,有这么一个神奇的地方---西二旗,这里坐落着中国最知名的IT公司群体:广联达,腾讯,百度,网易,新浪,联想,甲骨文,IBM,--(未来还会有大鸟软件:www.bigbird.wang,啊哈哈哈--). 工作生活在这里的一群人--旗人!区别三里屯的"屯儿里的人",亦庄的"庄儿里的人",中关村的"村儿里的人",这群人有点精神分裂,有点完美主义强迫症,很可爱,也很多金,却不似寻常之人,自成一体. 这群人爱看博客,爱写博客,爱把听到的,见到的一切