月度归档:2016年10月

《程序员必读之软件架构》–笔记

架构是什么

架构作为名词解释时,概括起来都与结构有关:将产品分解为一序列组件、模块和交互。

架构作为动词来解释时,包括了理解你需要构建什么、设定愿景以便进行构建和做出恰当的设计决策。所有这些都以需求为基础,因为需求驱动架构。关键在于,架构是关于交流愿景以及引入技术领导力的,这样参与构建产品的每个人都能理解这个愿景,并为产品的成功做出积极贡献。

不论何种领域的架构,其实主要就是结构和愿景。

架构分类

应用程序架构的关注点是应用程序,通常包括将应用程序结构为类和组件,确保设计模式正确应用,构建或使用框架,等等。本质上,应用程序架构谈论的是软件设计的低级别切面,通常只考虑单一的技术栈。应用程序架构着重考虑软件和代码组织。

系统架构是更大规模的应用程序架构。大多数软件系统实际上是由横跨不同层次和技术的多个应用程序组成。系统架构还关注互操作性和与环境中其他系统的集成。系统架构描述为从组件和服务到子系统等高层次的抽象。系统架构的定义大多数还包括了软件和硬件。

软件架构就是应用程序和系统架构的结合。从代码结构和基础到将代码成功部署到生产环境,与一个软件系统重要元素相关的所有东西就是软件架构。

企业架构一般是指整个组织的中心工作,着眼于如何组织和利用人员、流程和技术来使企业有效和高效地工作。它是关于企业如何分成组或部门,业务流程如何在这上层运作,以及技术如何支撑这一切。

好的架构带来敏捷。

软件架构角色

架构 VS. 设计

作为名词,设计是指一个系统内命名的结构或行为,解决或有助于月解决该系统的一个或多个问题。因而,设计代表了潜在的决策空间中的一个点。

所有架构都是设计,但并非所有设计都是架构。

架构反映了使一个系统成型的重要设计决策,而重要性则通过改变的成本来衡量。

尽管“重要决策”没法彻底消失,但能通过架构分层等多种策略来改变。软件系统架构流程的一部分就是搞清楚哪些是重要的及为什么。

思考软件架构的好处

  • 让团队跟随一个清晰的愿景和路线图,无论这个愿景是一个人所有还是整个团队共有;
  • 技术领导力和更好的协调;
  • 与人交流的刺激因素,以便回答与重要决策、非功能需求、限制和其他横切关注点相关的问题;
  • 识别或减轻风险的框架;
  • 方法和标准的一致性,随之而来的结构良好的代码库;
  • 正在构建的产品的坚实基础;
  • 对不同的听众,以不同层次的抽象来交流解决方案的结构。

C4:语境、容器、组件和类

c4: 语境 容器 组件 类
软件的静态视图:

  • 语境:设定场景的高层次图,包括关键的系统依赖和参与者。

    语境图帮助回答下面的问题:

    1. 我们构建的(或已经构建的)软件系统是什么?
    2. 谁会用它?
    3. 如何融入已有的 IT 系统?
  • 容器:荣企图显示了高层次的技术选择,容器如何分担职责、如何通信。

    1. 软件系统的整体形态是什么样的?
    2. 高层次技术决策有哪些?
    3. 职责在系统中如何分布?
    4. 容器之间如何相互交流?
    5. 为了实现特性,作为一个开发者,我需要在哪里写代码?
  • 组件:组件图可以让你看到每个容器的关键逻辑组件及之间的关系。

    1. 系统由哪些组件/服务组成?
    2. 在高层次上,系统如何工作是否清晰?
    3. 所有组件/服务都有一个家吗(即驻留在一个容器中)?
  • 类:可选的细节层次。

原则

约束通常是强加于你的,而原则是你为了将一致性和清晰度引入最终代码库而想采用的原则(如编码规范、自动化测试等)或架构的原则(如分层策略,架构模式等)。

%e5%85%b3%e6%b3%a8%e7%82%b9

《代码简洁之道–Clean Code》 摘记

第 2 章 有意义的命名

  • 名副其实: 变量、函数或类的名称应该告诉你,它为什么会存在,它做什么事,应该怎么用。如果名称需要注释来补充,那就不算名副其实。
    代码的模糊度:即上下文在代码中未被明确体现的程度。

  • 避免误导: 提防使用不同之处较小的名称。

  • 做有意义的区分: 要区分名称,就要以读者能鉴别不同之处的方式来区分。

  • 使用读得出来的名字。

  • 使用可搜索的名称 : 长名称胜于短名称,搜得到的名称胜于自造编码代写就的名称。单字母名称仅用于端方法中的本地变量。名称长短应与其作用域大小相对应。

  • 避免使用编码 : 不要用类型前缀、特定前缀来标记成员。

  • 避免思维映射 : 聪明程序员和专业程序员之间的区别在于,专业程序员了解,明确是王道

  • 类名 : 类名和对象名应该是名词或名词短语。

  • 方法名 : 方法名应当是动词或动词短语。重载构造器时,使用描述了参数的静态工厂方法名。

  • 每个概念对应一个词 : 给每个抽象概念选一个词,并且一以贯之。

  • 别使用双关语;

  • 使用解决方案领域名称 :

  • 使用源自所涉问题领域的名称;

  • 添加有意义的语境

  • 不要添加没用的语境 : 精确是命名的要点。

取好名字最难的地方在于需要良好的描述技巧和共有文化背景。

继续阅读

《 Reactive Microservices Architecture 》 响应式微服务架构 摘记

第三部分未完结,挖坑先。。。

第一章 介绍

我们只在我们没有其他选择时改变单体 (monolithic) 系统。与其说是敏捷地抓住机会,我们考虑它是否确实值得倾覆我们称为纸牌屋的企业系统的微妙平衡。通常,机会很快就消失了,被快速的公司抓住。

Flaus Schwab: 在新世界,不是大鱼吃小鱼,是快鱼吃慢鱼。

基于微服务的架构是个简单的概念:它提倡用一组小的、隔离的服务来创建系统。这些服务拥有它自己的数据,各自是独立的、可扩展且对失败有弹性。服务集成其他服务来构建一个内聚的系统,它比我们当前构建的典型企业系统更灵活。

传统企业系统设计为单体应用,难以扩展,难以理解且难以维护。单体应用可能很快就变成噩梦,扼杀创新、进度和乐趣。单体应用导致的负面作用对一个公司可能是灾难性的,从底层的士气到高层雇员的周转,从阻止公司雇佣顶尖工程天才到失去市场机会,在极端情况下,甚至是公司的失败。

战争故事通常听起来是这样的:“我们终于做了决定来改变我们的 Java EE 应用,在得到管理层批准后。然后我们经过长达数月的大设计,在我们最终开始构建点东西之前。但我们构建期间的大多数时间都花在尝试弄清楚单体应用真正做了什么。我们因害怕而瘫痪,担心一个小的错误可能导致非预期的、未知的副作用。最终,在数月的担忧、害怕和艰难工作后,改变实现了,但地狱也打开了。”

这样的经历会加强害怕,使我们瘫痪更严重。这就是系统、公司如何停滞的。如果有更好的方式呢?

Steve Jobs:You’ve got to start with the customer experience and work back towards the technology 。

微服务的客户是投资于系统的组织,所以让我们从客户开始:开发人员、架构师和关键利益相关者。

需要拯救的服务

Helen Keller:Although the world is full of suffering, it is also full of the overcomming of it .

因为技术原因,微服务是软件里不纯粹的下一代设计演进。微服务这个词汇呈现的思想在我们进入面向服务的架构(SOA, Service Oriented Architecture)之前已经遍布各处。阻止我们采用微服务内嵌的概念的特定技术约束已经进入下一水平:单台机器运行着单个内核处理器,慢速的网络,昂贵的磁盘,昂贵的 RAM,组织结构是个单体。像把系统组织成一个定义良好的、有单一职责的系统的想法不是新的。

快进到 2016 年,阻止我们采用微服务的技术限制已经消失了。网络是快速的,磁盘是便宜的(且更快速),RAM 是便宜的,多核处理器是便宜的,云架构正在彻底改革我们如何设计、部署系统。现在,我们终于可以考虑着客户来构建我们的系统。

设计和编写软件是有趣的,这是大多数的我们进入软件行业的初衷。微服务不仅仅是一序列的原则和技术。它们以一种更专业的方式来达成复杂问题的系统设计。

微服务允许我们以组织我们团队的方式来构建系统,在团队成员之间划分职责,保证他们自由处理自己的工作。当我们理顺了我们的系统,我们把权利从中央治理主体移交到小团队里,小团队可以快速抓住机会并保持敏捷,因为他们明白 他们控制的、有定义良好的边界的软件。

继续阅读

Spring AOP 与 事务实现

1. AOP 与方法调用

对于 接口 interface,可以通过 java.lang.reflect.Proxy 来生成动态代理对象;
对于 类 class,可以通过字节码技术,如 CBLIB 来生成一个子类作为代理对象,此时类不能声明为 final 。

当 Spring 把 Bean 注入到另一个 Bean 时,其实注入的是它生成的代理对象,进行方法调用时,首先调用的是代理对象上的方法,代理对象的方法最终再调目标对象的方法,也就是开发人员编写的方法。Spring 通过在调用目标方法前后做处理来实现一些特性,例如事务管理、缓存等。

Spring 的 AOP 是基于对代理对象的方法调用的拦截的,只能拦截外部对象 对 某个对象的方法的调用,对象的方法调用同一个类的方法是不会被拦截的。

@Service
public class SpringTxService {
    private static final Logger LOGGER = LoggerFactory
            .getLogger(SpringTxService.class);

    @Transactional(propagation = Propagation.REQUIRED)
    public void add() {
        LOGGER.info("do add");
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void requireNew() {
        LOGGER.info("do requireNew");
    }

    public void composite() {
        add();
        requireNew();
    }
}

上面的代码是基于注解进行事务控制的,composite 方法没有声明事务属性,它会调用 add、 requireNew
方法。当把 SpringTxService 注入到另一个 BeanB:
1. 在 BeanB 的方法里调用代理对象 composite 时,最终执行 add、 requireNew 是没有在事务里执行的,只是普通的方法调用。
2. 在 BeanB 的方法里调用代理对象的 add、 requireNew 方法时,这两个方法都会分别在相应的事务里执行。

当发现基于 AOP 实现的特性没有预期的效果时,一定要看看是不是在代理对象上调用还是目标类内部的方法调用。

继续阅读