阅读更多

2顶
0踩

企业架构



编者按:本文作者王庆友,前 1号店首席架构师,先后就职于 ebay、腾讯、1号店、找钢网,精通电商业务,擅长复杂系统业务建模和架构分析,目前在中国 B2B 第一电商公司找钢网担任首席架构师,微信号Brucetwins,欢迎一起聊架构。

目前讨论架构实操(术)的文章较多,讨论架构理念(道)的较少,本文基于作者在大型电商系统架构方面的一些实践和思考,和大家聊聊架构理念性的东西,希望能够抛砖引玉,推进大家对架构的认识。

什么是道,什么是术?道是事物发展的本质规律,术是事物发展的具体途径。规律只有一个,途径很多,条条大路通罗马,罗马是道,大路是术。道为本,术为途,如果事先知道罗马在哪里,那么遍地是路,路路相通。架构也是如此,如果能领悟架构的本质,就不会拘泥于现有的实践和理论框框,而以最直接的方式解决问题,无招胜有招。本文的内容包括架构的本质、架构的服务对象、架构师能力模型 、架构境界等。

架构本质
任何系统,自然情况下,都是从有序到无序,这是有科学依据的, 按照热力学第二定律,自然界的一切自发过程都有方向性,一个孤立系统会由有序变为无序,即它的熵会不断增加,最终寂灭。但生物可以通过和外界交互,主动进 行新陈代谢,制造 “负熵” 来保证自身有序,继续生存。

同样,一个软件系统随着功能越来越多,调用量急剧增长,整个系统逐渐碎片化,越来越无序,最终无法维护和扩展,所以系统在一段时间的野蛮生长后,也需要及时干预,避免越来越无序。

架构的本质就是对系统进行有序化重构,不断减少系统的 “熵”,使系统不断进化。

那架构是如何实现无序到有序的呢? 基本的手段就是分和合,先把系统打散,然后重新组合。



分的过程是把系统拆分为各个子系统 / 模块 / 组件,拆的时候,首先要解决每个组件的定位问题,然后才能划分彼此的边界,实现合理的拆分。合就是根据最终要求,把各个分离的组件有机整合在一起,相对来说,第一步的拆分更难。

拆分的结果使开发人员能够做到业务聚焦、技能聚焦,实现开发敏捷,合的结果是系统变得柔性,可以因需而变,实现业务敏捷。

举个例子,在 Web 1.0 时代,一个 ASP 或 JSP 页面里,HTML 和脚本代码混在一起,此时脚本代码越多,系统越混乱(即熵增加),最终连开发者自己都无法理解。此时就需要对系统重新架构,办法是引入 view helper 模式,分离 HTML 和脚本,HTML 成为 view,脚本成为帮助类。然后再简单整合在一起。通过重新分和合,整个系统层次清晰,职责明确,系统的无序度降低,容易扩展。同时不同技能的开发人员, 如 UED 和程序员,可以负责不同部分,有效提高开发效率。

好的架构就像一篇优美的散文,形散神不散,表面看无序,实则高度有序。

架构分类和服务对象
架构一般可分业务架构、应用架构、技术架构,那么它们分别解决什么问题,服务于谁呢? 我们首先看一个系统落地过程:



对于负责开发的人来说,怕的是业务太复杂,代码逻辑太乱,超出他能理解的范畴,系统无法维护。因此开发的需求是系统整体概念清晰,容易理解,方便扩展。

对于负责运行的机器来说,怕的是业务并发量太大,系统核心资源不够用(如数据库连接)。它希望在业务量增加时,系统能够支持水平扩展,支持硬件容错(如避免单点故障)。

开发的痛点主要由业务架构和应用架构解决,业务架构从概念层面帮助开发理解系统(动态的包括业务流程 / 节点 / 输入输出,静态的包括业务域 / 业务模块 / 单据模型)。

应用架构从逻辑层面帮助开发落地系统(应用种类 / 应用形式 / 数据交互关系 / 交互方式等),整个系统逻辑上容易理解,最近大家谈的比较多的 SOA 即属于应用架构的范畴。

机器的痛点主要由技术架构解决,如技术平台选型(操作系统 / 中间件 / 设备等),部署上希望支持多机房,水平扩展,无单点等。

强调一下,系统是人的系统,架构首先是为人服务的,业务概念清晰、应用逻辑合理、人好理解是第一位的(即系统有序度高)。现在大家讨论更多的是技术 架构,如高并发设计,分布式事务处理等,只是因为这个不需要业务上下文背景,比较好相互沟通。具体架构设计时,首先要关注业务架构和应用架构,这个架构新 手要特别注意。

架构师能力模型
架构师只做分和合的事情,但综合能力要求很高,要求内外兼修,下得厨房,上得厅堂,下图通过典型的架构方式介绍一个架构师的能力要求:



在此基础上,架构师要有技术的广度(多领域知识),又有深度(技术前瞻),对主流公司的系统设计非常了解,知道优劣长短,碰到实际问题,很快有多种方案可供评估。

抽象思维是架构师最重要的能力,架构师要善于把实物概念化并归类。比如面对一个大型的 B2C 网站,能够迅速抽象为采购->运营->前台搜索->下单->履单这几大块,对系统分而治之,庖丁解牛,早已目无全牛。

抽象思维是往高层次的总结升华,由实到虚;而透过问题看本质则是由虚到实,往深层次地挖掘。比如看到一段 java 代码,知道它在 JVM 如何执行;一个跨网络调用,知道数据是如何通过各种介质到达目标 (操作系统内核 / 网卡端口 / 电磁介质等)。透过问题看本质使架构师能够敏锐地发现底层之真实,系统性端到端地思考问题,识别木桶的短板并解决之。

能落地的架构才是好架构,良好的沟通能力确保各方对架构达成共识,愿意采取行动;良好的平衡取舍能力确保架构在现有资源约束下是最合理的,理想最终照进现实。

总结下,架构师的能力要求包括:
  • 兼具技术的广度(多领域知识)和深度(技术前瞻)
  • 兼具思维的高度(抽象思维)和深度(问题到本质)
  • 兼具感性(沟通)和理性(平衡)

架构境界
架构师从境界上由浅到深可以分为四层:第一看山不是山,第二看山是山,第三看山不是山,第四看山是山。



刚接手项目时,对业务不了解,时时被业务方冒出的术语弄得一愣一愣的,如果把现有问题比作山,则是横看成岭侧成峰,根本摸不透,此时看山不是山。

经过业务梳理和对系统深入了解,可以设计出一个屌丝的方案,把各个系统串起来,解决当前的问题,对当前这个山能够看清楚全貌,此时能够做到看山是山。

通过进一步抽象,发现问题的本质,原来这个问题是共性的,后续还会有很多类似问题。设计上进行总结和升华,得出一个通用的方案,不光能解决当前的问题,还可以解决潜在的问题。此时看到的已经是问题本质,看山不是山。

最后回到问题本身,去除过度的抽象,给出的设计简洁明了,增之一分嫌肥,减之一分嫌瘦,既解决当前问题,又保留最基本的扩展,此时问题还是那个问题,山还是那个山。

第一境界给不出合适方案,不表。

第二境界的方案只解决表面问题,往往设计不够,碰到其它类似问题或者问题稍微变形,系统需要重新做。

第三境界的方案往往过度设计,太追求通用化会创造出过多抽象,生造概念,理解和实现均困难,此时系统的无序度反而增加,过犹不及。

第四境界的方案,在了解问题本质的基础上,同时考虑现状,评估未来,不多做,不少做。

佛教讲空和色,色即事物现象,空即事物本质,从这个意义上说,第一重境界无色无空,第二重境界过色,第三重境界过空,第四重境界站在色和空之间,既色又空,不执着于当前,不虚无于未来。

不空不色,既空既色,道法自然,本性如来,架构之髓也。

来自:36氪
  • 大小: 74.4 KB
  • 大小: 232.9 KB
  • 大小: 55.1 KB
  • 大小: 62.1 KB
  • 大小: 80.2 KB
来自: 36氪
2
0
评论 共 2 条 请登录后发表评论
2 楼 arong 2016-03-03 10:47
有深度,境界不一样。
1 楼 wfh6732 2016-03-02 14:44
,哇, 好牛逼

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • Date类型的compareTo()用法

    Date类型的compareTo()用法

  • java中如何进行日期时间比较?4种方法介绍

    1. Date.compareto() java.util.Date提供了在Java中比较两个日期的经典方法compareto()。 1、如果两个日期相等,则返回值为0。 2、如果Date在date参数之后,则返回值大于0。 3、如果Date在date参数之前,则返回值小于0。 @TestvoID testDateCompare() throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-d

  • 在java中进行日期时间比较的4种方法

    1. Date.compareTo() java.util.Date提供了在Java中比较两个日期的经典方法compareTo()。 如果两个日期相等,则返回值为0。 如果Date在date参数之后,则返回值大于0。 如果Date在date参数之前,则返回值小于0。 @Test void testDateCompare() throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd&quot

  • 在 Java 中如何比较日期?

    在 Java 中有多种方法可以比较日期,日期在计算机内部表示为(long型)时间点——自1970年1月1日以来经过的毫秒数。在Java中,Date是一个对象,包含多个用于比较的方法,任何比较两个日期的方法本质上都会比较日期的时间。 本文主要介绍以下五种方式: 使用 Date.compareTo() 使用 Date.before()、Date.after() 和 Date.equals() 使用 Calender.before()、Calender.after() 和 Calender.equals...

  • Date的时间比较

    Date.before()、Date.after()、Date.equals() 获取本地时间和指定时间进行比较,此处使用了date时间比较的after方法,代码如下 public static void main(String[] args) throws ParseException { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); // 获取当天时间的第二天

  • Java里面使用Date.compareTo比较时间

    DateFormat dateFormat = DateFormat.getDateInstance(); Date oldTime = dateFormat.parse("2019-04-07 19:50:11"); Date newTime = new Date(); int result = oldTime.compareTo(newTime); System.out.println(res...

  • java 比较两个日期的先后

    // 比较两个时间的先后: day1 day2 (数据类型均为日期类型) Calendar c1=Calendar.getInstance(); c1.setTime(day1); Calendar c2=Calendar.getInstance(); c2.setTime(da

  • java Android中比较两个时间的大小 before函数和after函数的使用

    /** * 比较当前时间和服务器返回时间大小 * * @param nowDate * @param compareDate * @return */ public boolean compareDate(String nowDate, String compareDate) { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm"); try { Date now = df.parse(no.

  • R语言由浅入深:二、数据处理

    第二章、数据处理 一、变量的创建、编码、命名 将数据表示为矩阵或数据框仅是数据准备的第一步,数据分析时,大量的时间都花在了数据处理上 1.创建新变量 变量名<-表达式 2.算数运算符 运算符 描述 + 加 - 减 * 乘...

  • 常用类型(数据封装、Date、Calendar)简单介绍

    数据封装、Date、Calendar简单介绍 ​ 本文仅针对数据封装类型、Date类以及Calendar类进行简单介绍,说明部分方法。 1.数据封装 通常封装都是基本数据类型的单词首字母大写,比如Double->double,特殊的有Integer -> int Character -> char 以int类型为例,常用方法包括: 进制转换 转换2进制 Integer.toBinaryString(x); 转换8进制 Integer.toOctalString(x); 转换

  • R语言使用strptime函数和format格式化输出参数、R环境options参数把字符串转化为时间对象(输出的时间信息包含时、分钟、秒、微妙等信息)

    R语言使用strptime函数和format格式化输出参数、R环境options参数把字符串转化为时间对象(输出的时间信息包含时、分钟、秒、微妙等信息)

  • R语言使用as.Date函数将字符串转化为日期格式、基于当前日期和病例的生日计算病例的年龄(基于epiDisplay包的血压数据集)

    R语言使用as.Date函数将字符串转化为日期格式、基于当前日期和病例的生日计算病例的年龄(基于epiDisplay包的血压数据集)

  • 【R语言】关于as.Date函数报错缺失origin参数

    关于as.Date函数报错缺失origin参数 原因:原日期要是字符型数据 origin的含义和用法 含义 origin表示起始日期 用法 as.Date(2,origin=“2020-2-2”) #或者 as.Date(2,origin=“2020/2/2”) 返回结果:“2020-02-04” 原始日期不为字符型用as.Date.character() as.Date.character(20200202,format=“%Y%m%d”) 返回结果:“2020-02-02

  • R语言日期的表示和运算(详细总结)

    1、取出当前日期 Sys.Date() [1] "2014-10-29" date()  #注意:这种方法返回的是字符串类型 [1] "Wed Oct 29 20:36:07 2014" 2、在R中日期实际是double类型,是从1970年1月1日以来的天数 typeof(Sys.Date()) [1] "double" 3、转换为日期 用as.Date()可以将一个字符

  • R语言使用as.Date函数将R语言中的字符串(character)向量vector转化为日期向量、在as.Date函数中指定合适的format参数

    R语言使用as.Date函数将R语言中的字符串(character)向量vector转化为日期向量、在as.Date函数中指定合适的format参数

  • R语言-时间、日期函数使用

    R语言的日期主要涉及以下函数: Sys.Date():返回当前系统时间as.Date:转化为日期格式ISOdate(year, month, day):连接年月日并转化为时间格式 as.POSIXlt函数:主要提取年、月、日、某年第几天、某周第几天等 seq函数:主要构建时间序列函数,对数字序列也适用 具体操作案例如下: #Date function Sys.Date()#r

  • check mysql is_MySQL检查Varchar日期是否在字符串日期之间(MySQL Check if Varchar Date is Between String Dates)...

    MySQL检查Varchar日期是否在字符串日期之间(MySQL Check if Varchar Date is Between String Dates)我有一个SQL数据库,我有一个字段,其中包含日期,如01/31/2014 ,它是varchar类型。 即使我有权访问这个数据库,改变结构现在是不受限制的。有没有办法检查Javascript中的字符串日期是否在数据库中我的varchar类型日期...

  • java 时间对比_在java中进行日期时间比较的4种方法

    1. Date.compareTo()java.util.Date提供了在Java中比较两个日期的经典方法compareTo()。如果两个日期相等,则返回值为0。如果Date在date参数之后,则返回值大于0。如果Date在date参数之前,则返回值小于0。@Testvoid testDateCompare() throws ParseException {SimpleDateFormat sdf...

  • datetime常用方法

    1.函数:datetime (1)用法:输入一个日期,来返回一个datetime类​ (2)格式:datetime.datetime(年,月,日,hour=,minute=,second=) 其中hour,minute,second可选 (3)附加类方法: today():返回本地当前时间 now():返回本地当前时间 utcnow():返回本地当前时间 fromtimestamp(时间戳):返回...

  • 使用R语言中的as.Date函数将字符串向量转换为日期向量

    使用R语言中的as.Date函数可以轻松将字符串向量转换为日期向量。我们可以使用默认的日期格式,也可以通过format参数指定特定的日期字符串格式。处理缺失值和不同日期格式的字符串向量也是常见的情况,as.Date函数提供了相应的解决方案。希望本文对你理解如何使用as.Date函数将字符串向量转换为日期向量有所帮助!

Global site tag (gtag.js) - Google Analytics