语言的底层技术抽象

可能你用过很多语言,也可能你对他们很熟悉,那么对于开发者而言,语言的底层技术是什么?

c是一个语言的最小集合,如果你去看最早一版的c教程《The C Programming Language》,你会发现它的几个特点:

  1. 最接近机器的语言
  2. 语言的最小+最全集合

其它的语言,比如:java,python,lua,php,都是在c语言的基础上构建起来的,当然,它们提供了更多的语言特性,比如:元数据、反射、容器等。

那么,c的核心是什么?大概是函数。

假设我们定义了2个函数:

void a() {…}

void b() {…}

单从需求上来讲,可以将函数拓展成lambda表达式、或者是右值(被赋值给某个变量)、当作某个类的方法(本质上也是函数,只是函数名称有它新的规则)。

如果考虑a 调用b,那么这个就会变得有趣:

a调用b 它是由3部分组成:a、调用、b(a和b都可以是一组函数、调用可以认为是引用)。

对于a,b而言,这里面有要分两种情况:

如果b先出现,比如:有一组接口实现字符串的接口,那么a直接参考接口文档,调用即可。

如果a先出现,比如:chrome浏览器,它是可以写插件的,它的方式就是插件必须按照某种方式来写(协议)才能被集成到chrome里面;spring boot 容器,如果想注入到spring boot 里面,必须使用注解注入,比如:@Bean,@Controller,@Service等。

本质上来讲,a能成功调用b,是遵循某种协议的,一点协议有了,其实a和b谁先出现都可以。若是没有协议,那么显然会变得有些复杂。这里面体现了接口协议设计的重要性。

对于调用来讲,就比较有意思了。你会发现调用这个操作上也能做手脚,变得复杂。调用只能被拦截(AOP),否则就会影响a 和b,给它们增加负担。

无论拦截做到a,还是b端,ab至少有一个是被自动加载的(假设加载者为容器,所谓自动加载,就是生命周期被托管,只有这样,ab的容器,才能对调用做手脚。

一般对调用做手脚,应用场景为:b调用前后的日志打印、调用b的性能监控等;这里面有几种方案:b上加注解(spring boot)、按b的名字的前后缀(测试用例),b所在的包名称等等,主要是基于b的属性找规律;如果是加注解,则需要语言支持反射功能(java很早就有反射功能,真是有远见)。

总之,现在你看到的很多语言的特性,都可以抽象为a调用b这个场景,只是复杂化了。

写在CSD培训之后

先前参加了公司组织的CSM培训,本身作为一个开发还是有点迷茫的。虽然Scrum敏捷开发实践从整体上,看起来解决了一些问题,但介绍方向偏多,更多的是在介绍敏捷开发方法论。并没有介绍如何实施敏捷开发。CSD培训正好弥补了这一点。

CSD培训总共分三天,三个主题:TDD,重构和持续集成。这三个主题正好解决了我先前的疑惑,分别说一下我的看法。

  • TDD

对TDD印象比较深的是下面这个图。

捕获

这个图展示了,一种开发方式的转变需要付出很大的努力。事实上,TDD也不是非常陌生的东西。但是它会对现有的开发方式有很大的改变。

早在我最初实习的公司里面,整个公司都在围绕着一款操作系统(Elastos)进行开发。测试对于整个系统的重要性不言而喻,任何小的修改都有可能导致整个系统跑不起来。当时的策略是,公司内有一个很大的测试部门会参与到测试用例的编写,除此之外,研发自己也会写很多的单元测试工具。由于Elastos项目开始的较早(2000),很多工具需要自己开发和集成。开发、测试、运维集合在一起,才能确保系统的正确性。

但在后面的很长一段时间,我所在的公司都在从事应用层面的开发。单元测试就不显得那么重要了,很多时候,功能能用就可以了。甚至在小一点的团队里面,测试是不需要的,研发会代替测试的工作。

对于敏捷开发而言,迭代频繁了,单元测试也显得更重要了,每一轮迭代需要确保以前做的功能是好的。另外,开发方式上也有变化。更多的是简化功能实现,不再设计很复杂的实现了,能满足现有的需求即可。

  • 重构

上面的TDD其实是基于如下的开发方式的:

捕获2

研发先按使用场景编写单元测试,然后再实现功能,最后跑单元测试,直到全部通过。在这个过程中会遇到一个常见的问题,代码在编写的过程中,会变的很乱。这个我在之前的开发中就有遇到过。解决这个问题的方法很简单,就是重构。反正有单元测试用例,重构的过程也变得很简单,而且不用担心会把功能改坏。从研发角度而言,问题会从代码层面转嫁到单元测试用例层面,即你需要完善用例,确保覆盖到尽可能多的可能性,从而保证代码的正确性。

对于重构,我是有研究的。在几年前,我就意识到写代码的层面,大致分四种:重构、设计模式、框架、软件架构(具体可以参见这里)。这四个层面实际上是用来应对需求的不确定性的程度,对于需求的稳定程序,给予不同的设计思路。

关于重构的另外一点是,它除了适用于自己写代码之外,还适用于对已有旧代码的维护。关于这一点,我以前没有深入的思考过,好在这一次有人总结了一些经验,作为书分享出来了(修改代码的艺术),我觉得这也是我对重构这一部分比较大的收获之一。

  • 持续集成

持续集成这一块,看似属于运维层面,因为用到了一些运维的工具。但我认为,这一块仍然和研发有十分重要的关联。

如果一个团队二三十个人,开发一个框架,这个时候,持续集成的作用就很大了。它可以确保,单个成员修改的代码,不会影响到其它的功能。下面这张图很好的展示了持续集成的作用:

捕获3

在我现在的公司,这一块是归运维团队管的。所以,基本上无法实施学到的东西。最多就是可以给运维团队一些建议。

最后要说的是CSD培训是CSM培训很好的补充,对研发有很大的启发性。实际上,在实施敏捷开发的过程中,好的实践总会慢慢涌现出来的。你所要做的就是,随时准备着,迎接能提升你效率的方式、方法。