Go stream让go流动起来~

Java的Stream编程 自从Java 8将函数式编程引入语言后,该语言通过Lambda表达式和Stream库两者的结合,展现了全新的编码方式。实现了简洁,高效,以及类似声明式的编码风格。 举个例子,如我们有个集合里面存放的是颜色的标签,我们想在集合中找出以“b”字符开头的标签,并进行排序,然后转换成大写字符标签,最后输出。如果用Java 8以前的编码方式,我们会进行多次轮询,最后输出结果: public static void main(String[] args) { List<String> colors = Arrays.asList("blue", "green", "brown", "grey", "red", "white", "black", "beige", "purple"); List<String> filteredAndSortedColors = new ArrayList<>(); for (String color : colors) { if (color.startsWith("b")) { filteredAndSortedColors.add(color); } } Collections.sort(filteredAndSortedColors); for (String color : filteredAndSortedColors) { System.out.println(color.toUpperCase()); } } 如果用Java 8的Lambda、Stream来实现,则代码会更加简洁、易懂,执行效率也会提高: public static void main(String args[]) { Stream.of("blue", "green", "brown", "grey", "red", "white", "black", "beige", "purple") .filter(s -> s.startsWith("b")) .sorted() .map(s -> s.toUpperCase()) .forEach(System.out::println); } Go的Stream编程 go语言中函数是第一公民,理论上我们可以实现更简洁的Stream框架。Stream的核心有以下几个方面: ...

December 28, 2023

“敏捷”与“瀑布”,在中国还真相遇过,只不过不是你认为的方式

最近敏捷圈发起一阵讨论:敏捷、瀑布,在中国存在过吗,不禁思考在中国敏捷与瀑布,真没相遇过吗? 2000年前后,CMM思想流入中国,01年《程序员》杂志开始以《CMM布道中国》为专题进行一系列讲述。从这时起CMM在中国如火如荼的发展,IPD-CMMI一度成为众多企业的学习对象。在这股思潮下,软件开发以瀑布V模型为主,该流程要求软件发现缺陷后,需向上回溯到最早缺陷引入点,随后从缺陷引入点开始进行一系列后续变更。举个例子在测试阶段发现程序缺陷,通过分析后得知是需求文档描述有误,那么需要先变更需求文档,接着变更概要设计,详细设计,测试用例,代码修改,单元测试,代码评审,最后该功能重新进入测试阶段。 这个流程里需求分析,开发,测试人员通常属于各自职能部门,由于职能竖井(KPI,部门墙等),软件开发过程中经常需要开会协调。但只要时间充足,上线软件倒也质量尚可。但问题就出在时间充足这个假设前提,当时中国IT企业大多是以倒排期和版本火车方式进行项目计划。团队成员在同一时间会投入到多个软件版本中,时间紧,任务重,同时白天大部分时间又用于开会和扯皮,晚上才能安静的进行软件开发,长此以往团队陷入软件泥潭,疲惫不堪。 这时团队往往采取流程裁剪这样的骚操作,概要设计,详细设计,测试用例,单元测试,代码评审等非直接编码活动统统拆剪掉。剩下哪些活动呢?总得有需求文档吧,不然团队用什么开发,最主要的编码活动不能裁剪掉,就这两个活动就可以交付软件了,可团队TL心里没底啊,测试环节也留下。于是乎V模型只剩下“需求-开发-测试”三个活动。如果企业流程不能随意裁剪,那么你仔细观察上线前一天团队在做什么,就会发现所有团队成员都在补写文档,至于这些文档和当前上线代码有什么关系,没人知道。你问这些团队这是什么开发方式,他们会说这是裁剪后的“瀑布流程”。 2008年前后,敏捷思潮开始在企业发芽,《硝烟中的Scrum和XP》和《持续集成》成为敏捷支持者的床头书,迭代增量开发,快速反馈成为敏捷的重要指导思想,上一活动的问题,尽量在下一活动反馈中找到并修复。自动化测试成为保证质量,快速反馈,快速发布的重要标志。团队实在受不了每夜写代码,开始纷纷上马敏捷开发。可是采用敏捷开发,之前的问题就解决了吗? 敏捷宣言第二句“工作的软件高于详尽的文档”,但团队选择性无视左边,专注到右边,你看敏捷不用写任何文档了,一阵欢呼。于是敏捷3355会议开起,需求澄清会议一开就是2,3天,会议室里面坐满黑压压一片,产品经理卖力念着需求文档,团队里三层,外三层各自玩手机。​总算结束,团队开始拆卡片,随后进入迭代开发,后期进入迭代测试。你看这个敏捷开发不就是换了个名词的“敏捷3355+裁剪后的瀑布流程”。久而久之团队开始抱怨,以前瀑布流程的时候可没那么多会议,敏捷开发咋那么烦琐,要不我们也把迭代演示,迭代回顾,代码评审,自动化测试,小批量交付等裁剪了,最后敏捷开发成为迭代进行的“需求-开发-测试”三个活动。你问这些团队这是什么开发方式,他们会说这是“敏捷开发”。 你看中国企业采取了”瀑布流程“、”敏捷开发“,怎么最后都是一个样子?这里原因很多,有人认为是企业倒排期文化,有人认为是需求变化太快,但有一个很重要的问题,团队里面真的是合格程序员吗?真的理解计算机科学吗?以下一些问题作为参考: 哪些算法,语言设计,操作系统,分布式计算,运用了fork-join思想? Java为什么放弃绿色线程,现在为什么又要开始支持虚拟线程? 设计模式,面向对象编程是灵丹妙药吗? 你写的代码会覆盖必要的单元测试吗? 抽象能力是计算机基础,编程语言,框架,系统,硬件进行大量的抽象,尽量隐藏细节,但并不意味着你可以不理解计算机基础,就到处调用框架,运用大量并发技术。深入团队编码,会发现并不是团队不愿意写单元测试,而是团队写的代码根本无法测试,更不用说从未写过单元测试。 选人的时候,从未考虑候选人计算机基础能力,编码内功,只要这个人能尽快上手项目就行,这个语言,那个框架玩的飞起来。你仔细观察这些团队,会发现他们的流程再次升级,变成“需求-拷贝、粘贴-人肉点点点”。中国IT发展了20,30年,系统升级了,语言升级了,框架升级了,工具也升级了,可团队能力升级了吗?

January 3, 2023

敏捷本质

敏捷宣言诞生至今已20多年,在众多挑战瀑布的方法中,它完美的完成了这次反叛,成为主流的方式。敏捷最早作为软件行业的开发方式,现在逐渐渗透到其他行业。 随着敏捷方法流行,越来越多的概念,方法论,实践被加了进来,“敏捷”开始变得臃肿,很多和敏捷八杆子打不着的方法也号称“敏捷”。人们开始在各种概念中迷失,敏捷的本质被逐渐掩盖。 敏捷首要解决的问题是小团队开发,两个披萨可以喂饱的团队(6~12个人),如下图敏捷的核心实践,都是针对小团队的一系列活动: 我认为整个敏捷开发活动最重要的是BDD和TDD两个实践,再辅以过程透明化,快速反馈与持续改进。 为什么这两个实践如此重要,整个软件开发活动中我们要解决的三个核心问题是: 如何确保充分理解了业务需求 如果确保技术上能实现该需求 如何确保开发出来的功能满足业务需求 BDD通过与业务达成一致的实例化需求,来确保我们理解了业务需求,如果我们不能写出验收用例,证明我们还没理解业务需求。验收测试用例用来衡量我们是否真正理解业务需求。 同时我们把验收用例自动化,通过自动化验收测试,来确保我们开发出来的功能是满足业务需求的。 TDD通过自动化测试,来确保我们技术上是可行的,如果不能写出自动化测试,就无法确保在当前技术框架下可以完成该功能开发。 这两个实践使我们的开发活动工程化,只有通过工程化,才能确保我们的需求透明化,开发透明化,验收透明化,才能得到快速反馈,最后才能根据反馈持续改进。 关于规模化敏捷,人类历史上是不缺乏大规模的组织活动(金字塔,巴拿马运河,登陆月球,原子弹等等等),敏捷是通过首要解决小团队问题,然后把大规模团队划分为小团队,来达到规模化效果。但如果不先解决小团队问题,规模化敏捷就会流于形式。举个例子,规模化敏捷的核心问题就是团队间协作,版本火车中投入最大,耗时最长就是整个版本开发活动,多个团队要在估算的时间完成某功能联调活动,如果团队不具备TDD能力,那么团队的任务估算无法保证,导致该功能无法按时联调,团队间产生等待,连锁反应到迭代末团队继续追赶任务,无法投入到下迭代需求分析活动中,影响一直持续到后续迭代。 最后关于敏捷价值观,在眼花缭乱的各种方法中,以及在我们教练辅导中,是否还秉承着Kent Beck提到最核心的敏捷价值观:勇气,沟通,反馈,简单。

August 14, 2022

泛型编程浅入浅出(C++, Java, Go)

今年3月随着Go 1.18版发布,引入了一个重大的语言特性:泛型编程。这个特性在发布前引起了一定的争议。崇尚少即是多的一边认为这个特性不是很必要,应该谨慎引入。另一边则认为这是语言必不可少的特性。最后Go的泛型还是如期而至 泛型编程在其他编程语言也遇到了不同的问题,比如在Java 1.0时是没有引入泛型编程支持,到了Java 1.5的时候引入了泛型,但由于引入时间过晚,有大量的标准库和第三方库无法支持,Java选择了妥协采用间接的类型擦除方式来实现泛型编程,导致泛型的使用复杂度增加,同时场景受限。而C++比较明智,一开始就支持泛型,所以在C++ STL标准库里面大量的算法都是采用泛型实现,整个语言体系中泛型占据了核心位置 学习一个语言的特性可以参考其他语言同样的特性,这样就可以了解这个语言特性实现是否设计合理,是否优雅,存在哪些局限性 语言版本: C++11 Java 11 Go 1.18 1. 泛型函数 泛型函数用来支持当一个算法用在多种数据类型上,为了避免重复的定义函数,而用泛型函数来支持 两个数据进行取小操作 //C++ template <class T> T min(T a, T b){ return a < b ? a : b; } //Java不支持 //Go func Min[T int|float64](a, b T) T { if a < b { return a } else { return b } } 2. 泛型函数-显示特化 当泛型函数用来支持一个算法用在多种数据类型上,但在某个类型数据上泛型函数的实现不适合该类型,那么我们可以显示特化该类型的实现算法 /C++独有 template<> string min<string>(string a, string b){ return a.size() < b.size() ? a : b; } 3.泛型类 泛型类的目的是创建一个集合类型,里面的各种数据类型可以进行相同的操作,泛型类避免了多个数据类型的重复定义 ...

July 3, 2022

断食·轻断食

最近因为未控制饮食,以及家附近游泳池关闭,导致体重持续上升,已经到了自己难以忍受的状态,148.5。 一直知道有一种可能比较健康的生活方式,轻断食,但一直不知道怎么实践,通过搜索发现有部记录片《进食 断食 长寿》,介绍了轻断食的理念。决定先尝试一下正常断食,计划断食4天半,每天吃一些蔬菜汤,维生素,卡路里在200左右,完成后采用5+2轻断食法维持健康。 4月开始 第一天 23号晚上暴饮暴食后,不再进食,24号白天中午,未感觉任何饥饿感,可能是头天晚上吃太多了,出去溜达溜达,中午也没午觉,下午继续办公,办公后进行骑行锻炼1.5小时。晚上回来感觉头有点晕,吃了半碗饭+一小份莴笋烧兔子,补充了一颗维生素,肚子咕咕叫,后面整体正常。晚上睡觉质量变差,睡眠变浅。网上查询是因为身体激素变化的原因,断食期间睡眠会出现没有以前好的状况。 第二天 25号早晨体重145.5,没有饥饿感,工作到中午一样没有多少睡意,中午出去溜达一圈。下午工作到16点时,困意来袭,小眯了一会儿。进行骑行锻炼1.7小时,感觉力气没有昨天多。晚上自制蔬菜+西红柿汤,大概卡路里在200以内,补充一颗维生素。 肚子继续咕咕叫,并伴有轻微腹泻,持续时间一整夜。晚上睡眠还是变浅,醒来几次。 第三天 26日早晨体重143.5斤。无头晕感觉,但觉得力气不足。喝水,补充一颗维生素。腹泻状态暂时消失。今天工作比较忙,晚上回家感觉心跳加快,有些不适,怕影响健康,停止断食,开始正常晚餐。 后续开展5+2轻断食+运动,5.9号测量体重为142斤,正常开始降低体重。 7月期间 加大运动量,体重降到130以下,身体并无不适 9~10月期间 由于疫情运动量减小,加强了断食间隔,断食日整天不吃。体重维持到126左右。但出现营养不良型脱发。在10月下旬恢复正常饮食,脱发继续。 11月初脱发减少恢复正常。考虑轻断食太重可能影响健康。开始恢复正常饮食,同时加强运动消耗。体重126左右。

April 23, 2022