关于编程技巧:提高效率-Or-增加成本开发人员应如何理解结对编程

作者:Michael Yang,云智慧架构师 什么是结对编程结对编程(Pair programming)来自于极限编程 XP(eXtreme Programming),是它的最佳实际之一。顾名思义,结对编程就是两个程序员坐在一起,用一台开发机进行结对开发。 需注意,在国内“老带新”,“徒弟带徒弟”的结对形式并非严格意义上的结对编程。因为“老带新”的结对形式资深程序员有更多的话语权,故而失去了结对自身的意义,因而这种结对模式只能算是新人造就的一种模式。 结对编程的实际模式在采纳结对编程实际时,不同的团队有不同的形式: 分工明确型: 一个人负责编写代码,另外一个人审查代码,负责代码的正确性和可读性;一个人负责具体设计,一个人负责代码实现;一个人写性能代码,一个人写测试用例。独特单干型: 两个人独特探讨对于所开发性能的架构设计、编码实现、测试方法等,而后轮流做输出和察看的工作。此模式很好地做到了信息共享,失去互补的成果。 结对编程如何进步工作效率结对编程是通过两个开发人员在同一个我的项目或者工作上并肩合作,轮流编写代码并查看合作伙伴的输入来进步工作效率,上面将具体解说结对编程进步工作效率的具体形式。 突破常识壁垒,互相学习编程技巧,并升高产品需要设计缺点;互相配合,加强代码和产品交付品质,无效缩小 BUG,从而缩小测试人员工作量;相互督促,缩小“摸鱼”工夫,无效进步工作工夫;互为 Backup,在能保障我的项目顺利进行的同时,可更好地解决人员流动。结对编程的价值从我的项目角度,进步了产品质量在个别工作编程中,因为集体的想法不免有忽略,脱漏和局限性,就会产生“本人看本人写的代码怎么都对”的误区。而在结对时,因为是两个人共同完成一个产品性能,所以单方能够站在不同的角度看到彼此的谬误,从而防止了集体主观误区。另一方面,在结对编程过程中,因为代码已被至多一个程序员进行了审查,因而能够让代码的设计、测试和编码更加敌对,缩小了缺点,从而进步了产品质量。 结对编程的模式也保障了产品的一个性能,代码实现构造至多能够被两个人晓得,两个人可相互造成 Backup,而不会呈现像惯例编程一个人销假或者到职,后续我的项目无奈推动的状况。此外,有些团队通过定期更换结对编程人员组合,以此保障团队中的每个成员都能相熟我的项目的各个功能模块,从而造成我的项目集体所有的气氛,以及防止了“一人责任制,自扫门前雪”的景象。 更重要的是,在业务需要开发过程中,难免会呈现缺点。在排查问题过程中,结对编程的开发人员无需本人主观排查判断,而是能够通过与本人协同搭档商议的模式攻克缺点,这样的成果在最终也往往会是翻倍输入。 从团队角度,更好的促成了团队合作气氛以及常识传递分享从团队角度登程,相比于传统独立工位“栅栏”的工作形式,结对编程一方面更好的实现了常识传递分享,另一方面,结对编程这种即时的沟通交流形式也让团队成员关系变得更加融洽,从而更有利于创立谐和的团队气氛。 依据“乔哈里视窗(沟通视窗)”的实践,在理论工作和人际交往中,独特的开放区越多,沟通起来也就越便当,越不易产生误会。当咱们向他人扩充咱们的公开象限时,就会更多的和对方建设良好的关系,结对编程便是很好的一种沟通模式。 沟通视窗四象限: 公开象限:本人晓得,他人也晓得;隐衷象限:本人晓得,他人不晓得;盲点象限:本人不晓得,他人晓得;潜能象限:本人不晓得,他人也不晓得。第一个区域,本人晓得他人也晓得的信息叫做公开区信息;第二个区域,本人晓得他人不晓得的信息叫做隐衷;第三个区域,本人不晓得他人晓得的信息叫做盲区信息;第四个区域,本人不晓得他人也不晓得的信息叫做未知区(潜能区)信息。 从集体角度,进步了集体能力与工作效率从集体角度登程,在结对单干时,集体不仅会从结对合作伙伴那里学到新的常识和技能,还能受到对方工作形式和态度的影响。尺有所短,寸有所长,每个人都有本人的长处和短处,值得被学习和尊重。当团队中的每个人的能力进步了,其实就是整个团队能力的进步。 工作效率上,结对编程让大家更专一在工作上,工作外的一些集体流动将不会进行。每个人都有本人要负责的工作,某种程度上,结对编程让两个人外部造成了一个互相监督,共同进步的小团队,为了团队工作的实现,两个人都会专一在本人的工作上,从而大幅提高工作输入的效率。 总结结对编程其实是在结对磨合中缓缓造成的一种团队独特价值观和文化。这个过程是漫长且耳濡目染的,在结对编程中必然经验一致和对立的过程,而很多团队在一致中就间接进行了实际,也就无奈看到结对带来的益处。因而,在开始结对编程之前,管理人员应全面地思考你的团队是否真的适宜结对编程。 开源福利云智慧已开源数据可视化编排平台 FlyFish 。通过配置数据模型为用户提供上百种可视化图形组件,零编码即可实现合乎本人业务需要的炫酷可视化大屏。 同时,飞鱼也提供了灵便的拓展能力,反对组件开发、自定义函数与全局事件等配置, 面向简单需要场景可能保障高效开发与交付。 点击下方地址链接,欢送大家给 FlyFish 点赞送 Star。参加组件开发,更有万元现金等你来拿。 GitHub 地址: https://github.com/CloudWise-... Gitee 地址:https://gitee.com/CloudWise/f... 万元现金流动: http://bbs.aiops.cloudwise.co... 微信扫描辨认下方二维码,备注【飞鱼】退出AIOps社区飞鱼开发者交换群,与 FlyFish 我的项目 PMC 面对面交换~

June 23, 2022 · 1 min · jiezi

JavaScript设计原则编程技巧及常用设计模式

【前言】最近阅读量了《JavaScript设计模式与开发实践》,收货颇丰,于是想写一点总结及感想 写一篇文章对于我的意义在于: 给别人讲述知识时可以发现自己掌握的是否牢固透彻,写的过程不断发现自己的不足,然后通过一些方式来解决问题,这也是一种学习过程;当然,写文章给别人看,也要从读者的角度出发,考虑他们想要从这篇文章获得什么,还有就是你想表达些什么给读者这种过程大概叫费曼学习法,图解:(图片来自网络,侵删) 这篇文章我想表达的是:学习设计原则设计模式的好处、介绍设计原则和设计模式、常用设计模式的实践、代码重构的具体方法、一些问题一些思考。你可以先读一遍带着疑问去阅读这本书籍或者阅读完书籍再来看这篇文章是否有助于你理解 一、为什么要学习设计原则、设计模式首先,设计原则、设计模式受用的目标人群我觉得是有一定的js基础且有一定的项目实践经历的开发者,不然的话,就算学习设计也是生搬硬套,收货甚微,当有了一定基础及实践之后,阅读本书之后有三种感觉: 你的某些代码就是书上的反例,醍醐灌顶的感觉你的某些代码已经实践了某些设计模式遵从了某些设计原则,但是你并不知道这样写代码是叫这个模式以及这个模式的全部优缺点或者你的代码还有更进一步优化的空间内心冷笑一声:哼 so easy... emmmmm,如果大佬还愿意继续阅读本文的话,希望大佬可以在评论区指点一二个人认为,JavaScript设计原则以及设计模式都只属于软件设计的一部分,但这意味着已经开始脱离了’API调用工程师‘的称号,开始接触编程思想,但是设计原则跟模式有限,只针对于代码层面。 打个比方:vue源码使用了xx模式,解决了xx问题,但是,在选择xx模式解决xx问题的背后又有多少思考????呢?简单猜测一下:一个框架or库 = 软件设计 + 其他框架优点借鉴 + 创新 + 编码 + 测试;本人水平有限,这是知识宏观的揣测一下实现一个框架or库需要的付出。请不要当真or较真 可能没人要你去写框架什么的,但是你负责的部分总是你来写来维护,不按套路出牌受伤的是自己举这个例子是想说明:学习一下设计原则设计模式是多么的有必要(强行解释,最为致命) 二、JavaScript常用设计原则我想提一个这本书的缺点,就是目录,设计模式都是要遵循设计原则的,而且很多设计模式章节都提到了设计原则,然而书的目录是最后一个大章节才说的设计原则,我觉得设计原则应该放在设计模式之前,所以建议先阅读设计原则再阅读设计模式,在理解上也会有帮助,至于第一章节的基础知识介绍,这个看各人情况可以选择要不要忽略 下面介绍常用的设计原则 1. 单一职责原则 SRP【定义】 单一职责原则的定义是‘引起变化的原因’,如果你有两个原因去修改一个方法,说明这个方法有两个职责,承担的职责越多你需要修改他的可能性就越大,修改代码总是件危险的事情,特别是两个职责耦合在一起的时候一句话概括:一个对象(方法)只做一件事【理解】 书上有介绍单一职责原则相关的模式,其实我觉得从原则去联系模式有点不合理,因为所有模式都会去遵从设计原则,知识侧重点不一样而已。所以我会在下个章节的模式里去联系原则,而说原则,我只想脱离模式单独去说原则的优缺点以及如何应用【优点】降低了单个类或者对象的复杂度,按照职责把对象分解成更小的粒度,这有助于代码的复用,也有利于进行单元测试。当一个职责需要变更的时候,不会影响到其他的职责。【缺点】增加编码复杂度,同时增加对象之间联系的难度 【应用】煮个栗子,js的组件化开发,有一种思想就是组件的原子化,把组件拆到不能再拆的粒度,是最好维护的。但事实真的是这样吗,组件多了,组件之间的联系也多了,就意味需要管理更多的组件及组件间的复杂关系,有时候明明两个组件像孪生兄弟一样分不开,你偏要拆散他们并且给他们一座桥梁去联系,这无疑比让他们在一起成为一个整体要难维护的多,而且颗粒度越小,代表着开发成本越大。 单一职责原则也是如此,这些思想其实建立在理想化的状态上,而实际情况往往不会与理想对等,所以实际项目使用中,要学会灵活多变,知道什么时候其实是可以违反原则的,借用书上的话: SRP 原则是所有原则中最简单也是最难正确运用的原则之一。要明确的是,并不是所有的职责都应该一一分离 一方面,如果随着需求的变化,有两个职责总是同时变化,那就不必分离他们。比如在 ajax 请求的时候,创建 xhr 对象和发送 xhr 请求几乎总是在一起的,那么创建 xhr 对象的职责和发送 xhr 请求的职责就没有必要分开。 另一方面,职责的变化轴线仅当它们确定会发生变化时才具有意义,即使两个职责已经被耦 合在一起,但它们还没有发生改变的征兆,那么也许没有必要主动分离它们,在代码需要重构的 时候再进行分离也不迟 个人认为这是理解最简单,实践最难的一个 // badvar createLoginLayer = (function(){ var div; return function(){ if ( !div ){ div = document.createElement( 'div' ); div.innerHTML = '我是登录浮窗'; div.style.display = 'none'; document.body.appendChild( div ); } return div; }})();// goodvar getSingle = function( fn ){ // 获取单例 var result; return function(){ return result || ( result = fn .apply(this, arguments ) ); }var createLoginLayer = function(){ // 创建登录浮窗 var div = document.createElement( 'div' ); div.innerHTML = '我是登录浮窗'; document.body.appendChild( div ); return div; };var createSingleLoginLayer = getSingle( createLoginLayer );var loginLayer1 = createSingleLoginLayer();var loginLayer2 = createSingleLoginLayer();alert ( loginLayer1 === loginLayer2 ); // 输出: true2. 最少知识原则 LKP单一职责原则说道:一个对象(方法)只做一件事;那代表着我们要创建更多的对象(方法)来分解一个之前比较大的对象(方法),那分解之后,对象(方法)是小了,好维护好扩展了,但是对象之间的联系缺越来越多了,有两个对象非常耦合,怎么办 ...

July 4, 2019 · 4 min · jiezi

Python 工匠:善用变量来改善代码质量

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~本文由鹅厂优文发表于云+社区专栏作者:朱雷 | 腾讯IEG高级工程师『Python 工匠』是什么?我一直觉得编程某种意义上是一门『手艺』,因为优雅而高效的代码,就如同完美的手工艺品一样让人赏心悦目。在雕琢代码的过程中,有大工程:比如应该用什么架构、哪种设计模式。也有更多的小细节,比如何时使用异常(Exceptions)、或怎么给变量起名。那些真正优秀的代码,正是由无数优秀的细节造就的。『Python 工匠』这个系列文章,是我的一次小小尝试。它专注于分享 Python 编程中的一些偏『小』的东西。希望能够帮到每一位编程路上的匠人。变量和代码质量作为『Python 工匠』系列文章的第一篇,我想先谈谈 『变量(Variables)』。因为如何定义和使用变量,一直都是学习任何一门编程语言最先要掌握的技能之一。变量用的好或不好,和代码质量有着非常重要的联系。在关于变量的诸多问题中,为变量起一个好名字尤其重要。如何为变量起名在计算机科学领域,有一句著名的格言(俏皮话):There are only two hard things in Computer Science: cache invalidation and naming things. 在计算机科学领域只有两件难事:缓存过期 和 给东西起名字 – Phil Karlton第一个『缓存过期问题』的难度不用多说,任何用过缓存的人都会懂。至于第二个『给东西起名字』这事的难度,我也是深有体会。在我的职业生涯里,度过的作为黑暗的下午之一,就是坐在显示器前抓耳挠腮为一个新项目起一个合适的名字。编程时起的最多的名字,还数各种变量。给变量起一个好名字很重要,因为好的变量命名可以极大提高代码的整体可读性。下面几点,是我总结的为变量起名时,最好遵守的基本原则。1. 变量名要有描述性,不能太宽泛在可接受的长度范围内,变量名能把它所指向的内容描述的越精确越好。所以,尽量不要用那些过于宽泛的词来作为你的变量名:BAD: day, host, cards, tempGOOD: day_of_week, hosts_to_reboot, expired_cards2. 变量名最好让人能猜出类型所有学习 Python 的人都知道,Python 是一门动态类型语言,它(至少在 PEP 484 出现前)没有变量类型声明。所以当你看到一个变量时,除了通过上下文猜测,没法轻易知道它是什么类型。不过,人们对于变量名和变量类型的关系,通常会有一些直觉上的约定,我把它们总结在了下面。『什么样的名字会被当成 bool 类型?』布尔类型变量的最大特点是:它只存在两个可能的值『是』 或 『不是』。所以,用 is、has 等非黑即白的词修饰的变量名,会是个不错的选择。原则就是:让读到变量名的人觉得这个变量只会有『是』或『不是』两种值。下面是几个不错的示例:is_superuser:『是否超级用户』,只会有两种值:是/不是has_error:『有没有错误』,只会有两种值:有/没有allow_vip:『是否允许 VIP』,只会有两种值:允许/不允许use_msgpack:『是否使用 msgpack』,只会有两种值:使用/不使用debug:『是否开启调试模式』,被当做 bool 主要是因为约定俗成『什么样的名字会被当成 int/float 类型?』人们看到和数字相关的名字,都会默认他们是 int/float 类型,下面这些是比较常见的:释义为数字的所有单词,比如:port(端口号)、age(年龄)、radius(半径) 等等使用 id 结尾的单词,比如:user_id、host_id使用 length/count 开头或者结尾的单词,比如: length_of_username、max_length、users_count注意:不要使用普通的复数来表示一个 int 类型变量,比如 apples、trips,最好用 number_of_apples、trips_count 来替代。其他类型对于 str、list、tuple、dict 这些复杂类型,很难有一个统一的规则让我们可以通过名字去猜测变量类型。比如 headers,既可能是一个头信息列表,也可能是包含头信息的 dict。对于这些类型的变量名,最推荐的方式,就是编写规范的文档,在函数和方法的 document string 中,使用 sphinx 格式(Python 官方文档使用的文档工具)来标注所有变量的类型。3. 适当使用『匈牙利命名法』第一次知道『匈牙利命名法』,是在 Joel on Software 的一篇博文中。简而言之,匈牙利命名法就是把变量的『类型』缩写,放到变量名的最前面。关键在于,这里说的变量『类型』,并非指传统意义上的 int/str/list 这种类型,而是指那些和你的代码业务逻辑相关的类型。比如,在你的代码中有两个变量:students 和 teachers,他们指向的内容都是一个包含 Person 对象的 list 。使用『匈牙利命名法』后,可以把这两个名字改写成这样:students -> pl_students teachers -> pl_teachers其中 pl 是 person list 的首字母缩写。当变量名被加上前缀后,如果你看到以 pl 打头的变量,就能知道它所指向的值类型了。很多情况下,使用『匈牙利命名法』是个不错的主意,因为它可以改善你的代码可读性,尤其在那些变量众多、同一类型多次出现时。注意不要滥用就好。4. 变量名尽量短,但是绝对不要太短在前面,我们提到要让变量名有描述性。如果不给这条原则加上任何限制,那么你很有可能写出这种描述性极强的变量名:how_much_points_need_for_level2。如果代码中充斥着这种过长的变量名,对于代码可读性来说是个灾难。一个好的变量名,长度应该控制在 两到三个单词左右。比如上面的名字,可以缩写为 points_level2。绝大多数情况下,都应该避免使用那些只有一两个字母的短名字,比如数组索引三剑客 i、j、k,用有明确含义的名字,比如 persion_index 来代替它们总是会更好一些。使用短名字的例外情况有时,上面的原则也存在一些例外。当一些意义明确但是较长的变量名重复出现时,为了让代码更简洁,使用短名字缩写是完全可以的。但是为了降低理解成本,同一段代码内最好不要使用太多这种短名字。比如在 Python 中导入模块时,就会经常用到短名字作为别名,像 Django i18n 翻译时常用的 gettext 方法通常会被缩写成 _ 来使用(from django.utils.translation import ugettext as _)5. 其他注意事项其他一些给变量命名的注意事项:同一段代码内不要使用过于相似的变量名,比如同时出现 users、users1、 user3 这种序列不要使用带否定含义的变量名,用 is_special 代替 is_not_normal更好的使用变量前面讲了如何为变量取一个好名字,下面我们谈谈在日常使用变量时,应该注意的一些小细节。1. 保持一致性如果你在一个方法内里面把图片变量叫做 photo,在其他的地方就不要把它改成 image,这样只会让代码的阅读者困惑:『image 和 photo 到底是不是同一个东西?』另外,虽然 Python 是动态类型语言,但那也不意味着你可以用同一个变量名一会表示 str 类型,过会又换成 list。同一个变量名指代的变量类型,也需要保持一致性。2. 尽量不要用 globals()/locals()也许你第一次发现 globals()/locals() 这对内建函数时很兴奋,迫不及待的写下下面这种极端『简洁』的代码:def render(request, user_id, trip_id): user = User.objects.get(id=user_id) trip = get_object_or_404(Trip, pk=trip_id) is_suggested = is_suggested(user, trip) # 利用 locals() 节约了三行代码,我是个天才! return render(request, ’trip.html’, locals())千万不要这么做,这样只会让读到这段代码的人(包括三个月后的你自己)痛恨你,因为他需要记住这个函数内定义的所有变量(想想这个函数增长到两百行会怎么样?),更别提 locals() 还会把一些不必要的变量传递出去。更何况, The Zen of Python(Python 之禅) 说的清清楚楚:Explicit is better than implicit.(显式优于隐式)。所以,还是老老实实把代码写成这样吧: return render(request, ’trip.html’, { ‘user’: user, ’trip’: trip, ‘is_suggested’: is_suggested })3. 变量定义尽量靠近使用这个原则属于老生常谈了。很多人(包括我)在刚开始学习编程时,会有一个习惯。就是把所有的变量定义写在一起,放在函数或方法的最前面。def generate_trip_png(trip): path = [] markers = [] photo_markers = [] text_markers = [] marker_count = 0 point_count = 0 … …这样做只会让你的代码『看上去很整洁』,但是对提高代码可读性没有任何帮助。更好的做法是,让变量定义尽量靠近使用。那样当你阅读代码时,可以更好的理解代码的逻辑,而不是费劲的去想这个变量到底是什么、哪里定义的?4. 合理使用 namedtuple/dict 来让函数返回多个值Python 的函数可以返回多个值:def latlon_to_address(lat, lon): return country, province, city# 利用多返回值一次解包定义多个变量country, province, city = latlon_to_address(lat, lon)但是,这样的用法会产生一个小问题:如果某一天, latlon_to_address 函数需要返回『城区(District)』时怎么办?如果是上面这种写法,你需要找到所有调用 latlon_to_address 的地方,补上多出来的这个变量,否则 ValueError: too many values to unpack 就会找上你:country, province, city, district = latlon_to_address(lat, lon)# 或者使用 _ 忽略多出来的返回值country, province, city, _ = latlon_to_address(lat, lon)对于这种可能变动的多返回值函数,使用 namedtuple/dict 会更方便一些。当你新增返回值时,不会对之前的函数调用产生任何破坏性的影响:# 1. 使用 dictdef latlon_to_address(lat, lon): return { ‘country’: country, ‘province’: province, ‘city’: city }addr_dict = latlon_to_address(lat, lon)# 2. 使用 namedtuplefrom collections import namedtupleAddress = namedtuple(“Address”, [‘country’, ‘province’, ‘city’])def latlon_to_address(lat, lon): return Address( country=country, province=province, city=city )addr = latlon_to_address(lat, lon)不过这样做也有坏处,因为代码对变更的兼容性虽然变好了,但是你不能继续用之前 x, y = f() 的方式一次解包定义多个变量了。取舍在于你自己。5. 控制单个函数内的变量数量人脑的能力是有限的,研究表明,人类的短期记忆只能同时记住不超过十个名字。所以,当你的某个函数过长(一般来说,超过一屏的的函数就会被认为有点过长了),包含了太多变量时。请及时把它拆分为多个小函数吧。6. 及时删掉那些没用的变量这条原则非常简单,也很容易做到。但是如果没有遵守,那它对你的代码质量的打击是毁灭级的。会让阅读你代码的人有一种被愚弄的感觉。def fancy_func(): # 读者心理:嗯,这里定义了一个 fancy_vars fancy_vars = get_fancy() … …(一大堆代码过后) # 读者心理:这里就结束了?之前的 fancy_vars 去哪了?被猫吃了吗? return result所以,请打开 IDE 的智能提示,及时清理掉那些定义了但是没有使用的变量吧。7. 能不定义变量就不定义有时候,我们定义变量时的心理活动是这样的:『嗯,这个值未来说不定会修改/二次使用』,让我们先把它定义成变量吧!def get_best_trip_by_user_id(user_id): user = get_user(user_id) trip = get_best_trip(user_id) result = { ‘user’: user, ’trip’: trip } return result其实,你所想的『未来』永远不会来,这段代码里的三个临时变量完全可以去掉,变成这样:def get_best_trip_by_user_id(user_id): return { ‘user’: get_user(user_id), ’trip’: get_best_trip(user_id) }没有必要为了那些可能出现的变动,牺牲代码当前的可读性。如果以后有定义变量的需求,那就以后再加吧。结语碎碎念了一大堆,不知道有多少人能够坚持到最后。变量作为程序语言的重要组成部分,值得我们在定义和使用它时,多花一丁点时间思考一下,那样会让你的代码变得更优秀。这是『Python 工匠』系列文章的第一篇,不知道看完文章的你,有没有什么想吐槽的?请留言告诉我吧。问答 如何从变量名中获取字符串?相关阅读鹅厂优文 | ReactJS一点通开发效率太低?您可能没看这篇文章用CSS画小猪佩奇,你就是下一个社会人! 【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识 ...

September 29, 2018 · 2 min · jiezi