zoukankan      html  css  js  c++  java
  • 键值对在架构设计里的应用

    1. 谈谈我对程序的理解

      作为程序员你对程序是如何理解的?写这篇文章的时候,我认真思考了下,发现我对程序的理解不是和教科书一样的,我每次听到程序二字我想到的只有两个东西:代码和数据,而每次写程序的时候也就是写代码操作数据的过程。

      做程序开发和做菜很像,数据就是食材,代码就是厨艺,做出的软件就是一道菜了,至于这个菜好不好吃,到底是看食材还是看厨艺了?呵呵,当我抛出这个问题的时候,我的第一反应是菜不好吃当然是手艺不好了,不知道其他童鞋是不是这么想的。认真想下,一道好菜一般都是二者必须兼备,当然不排除某一项突出也可以达到同样的效果,但这种情况毕竟不是大众化,而是属于少数精英的,做软件也是如此,代码与数据是不可偏废的。这里我要提的是数据。

      根据我的经验和知识(分类标准我一直想不太好,所以说是自己的经验和知识),我把数据分为两类:落地数据和不落地数据。

    1. 落地数据:就是被持久化的数据,这种数据一般放在硬盘或是其他的持久化存储设备里,例如:图片、系统日志、在页面上显示的数据以及保存在关系数据库里的数据等等,落地数据一定会有一个固定的载体,他们不会瞬时消失的。
    2. 不落地数据:一般指存储在内存或者是网络传输里的数据,这些数据是瞬时,使用完毕就会消失,例如:我们在浏览器发送给服务器的请求;从数据库读取出来的一直到页面展示前的数据等等。

      写过程序的人都知道,程序里对这两种类型数据操作是有很大的不同的。

       2.由javaEE的mvc设计模式谈起

     java一个很重要的贡献就是推出了mvc设计模式,mvc其实应该按vcm顺序读最好。v及view,主要是前台展示的页面;c及controller,控制层主要作用是接受前台页面数据,根据数据的不同调用后台不同的业务模型,同时业务模型处理好的数据也要发送到controller,controller再分配给相应的前台页面;m及model,模型层专门负责操作业务模型。下图很好的表达了mvc的理念:

    随着mvc模式的发展,现在流行的架构:view(视图层)+controller(也叫action,控制层)+service(业务模型层)+DAO(数据访问对象层)+数据库的多层结构,如下图:

     

    红线是用户的请求;蓝线是服务器响应用户的请求。红色和蓝线也代表各层数据传输的流向。

    不管是传统的mvc模式还是现在流行的多层架构, 各个逻辑层传输的数据都是不落地数据。

    在java项目里,一般我们都是传输javabean,而这些javabean都是程序员根据实际业务需求自己定义的,例如下面一个典型的javabean:

    public class User {

    private String name = "";
    private String sex = "";
    private String age = "";
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public String getSex() {
    return sex;
    }
    public void setSex(String sex) {
    this.sex = sex;
    }
    public String getAge() {
    return age;
    }
    public void setAge(String age) {
    this.age = age;
    }



    }

    各个逻辑层传输javabean对象的观念一定会深入很多java程序员的人心,当一个项目开始,程序员都会吭哧吭哧的创建javabean对象,比如数据库表映射的javabean,在struts1.2里还有页面表达对应的javabean,做了这么多年这样的javabean,现在我就思考,使用javabean真是最好的选择吗? 

    3.Nojavabean

    我这里借用现在很流行的NoSQL的定义作为我文章第三部分的标题。javabean已经深入很多java程序员心理,甚至是很多程序员的习惯,其实它真的那么好用吗?真的那么包治百病吗?其实不尽然,下面我要列举它的缺点:

    1.javabean的文件太多。一个java企业项目,都会使用orm,将数据库映射为java对象,一般一张表对应一个javabean,甚至有些特殊情况还会归并一些表做一个统一的javabean,如果这个系统有1000张表也就会有不少于1000个javabean,在原始的struts1.2里面还有和页面表单字段一一对应的javabean,大伙可以想象下,这些毫无技术含量的java类也许会像病毒一样去繁殖。

    2.javabean会增强各层之间的耦合度。每个层里运算结束,业务数据大多会被封装成javabean对象,不同的业务封装的javabean是不同的,mvc本来就是为逻辑层解耦做的设计,而传输介质却是包含业务逻辑,如果碰到业务层级的修改,各个层之间都会有相应的结构性修改,增加了维护的成本。

    3.我们至少会多维护一份数据字典。数据库里的某张表一个字段叫USER_NAME,那么到了javabean里可能就变成了userName,当然我们在orm会有一个映射模型,但是随着数据一层层传递,离数据库越远的数据,数据的本质也就越模糊,特别会给新手产生一定误解,增加了软件开发和维护成本。

    4.这个是缺点是我的在实际项目里碰到的一个难题,我还没把它总结成一个概括性的缺陷,但我相信会有童鞋碰到类似的问题。我在一个项目里做权限管理,因为某些数据的敏感性我们要做数据集的权限,比如某些人只能查看当天的数据,还有些人只能看当天数据前10条,另一些人只能看最近一个星期的数据,而且只有三个字段能让他查看。由于权限管理是在该项目三期的任务,我们的权限设计是在原有的系统上进行开发,而且包含两个不同项目,其中一个项目是使用javabean做传输介质,另一个我们用了另外的方式,最后这个javabean成了我们的梦魇,为了做一个通用解决方案,我们将用javabean作为传输介质的项目重构了一下,增加了不少工作量。

    5.mvc分层思想,其实是为了让专业的人做专业的事,擅长做页面的做页面,擅长逻辑的做逻辑,按mvc思想项目开发往往是横向分组的,但是实际开发中,没人敢这么分配工作,究其原因就是层与层直接传输的介质并不统一。

    既然我的标题是Nojavabean,not only javabean,那么就像NoSQL能弥足SQL数据库的不足,以上的不足我们用什么技术来弥补了?

    答案就是:键值对。

    4.万能的MAP(键值对)

     google的三篇论文带来了云时代,用博大的胸怀改变了世界,而这里面最关键的东西就是map(键值对),key-value模式(后面简称kv)+数组我个人觉得基本可以表述这个世界的90%了。而且基本所有的语言都支持kv的数据结构,这件kv是多么强大的数据结构,世界就是被这个简单方式而改变的。(本来我想谈谈kv在云计算存储和计算的作用,作为本文主题的补充,但是时间限制,大伙可以自己查阅下相关资料)。

    我的替代数据模型就是用map作为数据传输介质,让我产生这个想法的源头是三个技术:mapreduce,ibatis和json;我们中心很重视hadoop技术,我们这里经常做hadoop相关技术分享,听来听去都有什么mapreduce,都是map,map;而我们现在公司的项目都是用ibatis做orm,当时表很多,我一时偷懒不是所有的ibatis配置文件都和javabean一一对应,只是返回一个map对象,如果是列表查询就是List<Map>,没想这么做居然有意外的收获,因为页面数据我们都是封装成json对象,json其实也是一个键值对的模型,数据到了action也是被传化成了map,所有返回值一样,居然提升了整个开发的效率,而且项目里面少了javabean对象,显的清爽多了。

    下面我总结下map的好处,在文章第三部分写道了javabean的缺点,这些缺点倒过来看就是map的优点了,我这里就不再复述了:

    1.不管什么技术从map取值的方式是统一的:例如在javascript里面json:

     

    obj.XXX或者obj[XXX]

    java里的map:

    map.get(XXX)或map.put(XXX)

    map取值方式是用key,key是字符串,是可以随时定义,而javabean是通过定义的方法读取,如果使用map会将传输数据的业务属性封闭在map内部,这样带来了操作的方便。

    2.map技术几乎在所有的主流技术里面都有,那么用这种数据结构作为传输介质是跨平台的

    3.map数据结构算法很成熟,做复杂计算是十分方便。

    ok,写道这里吧,还有很多东西没讲清楚,写的太累了,明天还要起早赶火车,我的这个想法抛出来就是想听听大伙的意见,现在有点着迷map了,不知道将我们把各个逻辑层用map这种数据结构做传输是不是会带来更多的开发便利,很希望听到大家的意见。

  • 相关阅读:
    Leetcode 16.25 LRU缓存 哈希表与双向链表的组合
    Leetcode437 路径总和 III 双递归与前缀和
    leetcode 0404 二叉树检查平衡性 DFS
    Leetcode 1219 黄金矿工 暴力回溯
    Leetcode1218 最长定差子序列 哈希表优化DP
    Leetcode 91 解码方法
    Leetcode 129 求根到叶子节点数字之和 DFS优化
    Leetcode 125 验证回文串 双指针
    Docker安装Mysql记录
    vmware虚拟机---Liunx配置静态IP
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2195501.html
Copyright © 2011-2022 走看看