前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一周技术思考(第27期)-爱情会骗你,但代码永远不会

一周技术思考(第27期)-爱情会骗你,但代码永远不会

作者头像
王新栋
发布2021-08-20 10:33:38
2720
发布2021-08-20 10:33:38
举报
文章被收录于专栏:程序架道

大家好,这里记录,我每周读到的技术书籍、专栏、文章以及遇到的工作上的技术经历的思考,不见得都对,但开始思考总是好的。

图片
图片

代码是唯一的真相

不知道,你是否遇见过这种情况,就是代码的注释,跟代码实际在做的事情,并不一致。

这种情况你怎么办,相信注释,还是相信代码。

不知道,你是否还遇到过这种情况,就是你看了架构设计图,然后再看工程代码,发现它们之间对应不上。

这种情况你又该怎么办,相信架构,还是相信代码。

大多数人,肯定是相信代码,对吧,毕竟它正在线上跑着。

也正是基于这个现实情况,所以我们才会喊出来,代码是最诚实的

注释跟代码不一致,架构设计有时候也会跟代码脱节,有时候就发生在我们的现实中。。

墙上的架构图说的是一回事,代码说的却是另一回事。

代码是诚实的,但不一定就是说架构师不诚实,而有可能是架构师也没有把架构设计和工程代码做好落地的衔接

比如,我们在软件开发里面做组件设计,一般情况下,当考虑一个组件的时候,有一种最简单的方式,那就是认为组件是接口背后的一组相关行为,可以用一个或多个协作类实现

我们希望的是,我们的组件被使用的时候必须是“力出一孔”的。

但,不幸的是,当你看完架构设计图,再去看代码的时候,在工程代码结构上就已经背叛了这样的原则。

下面这个包的分层结构,想必大家已经很熟悉了,典型的按层封装的方式。这种封装代码的方式本身是没有错误的,比如我们常用的MVC结构,它可以让工程代码清晰的结构化。

图片
图片

但是,在组件化设计上,它有一个最大的弊端,就是我们想要的“力出一孔”的组件,其实变成了“力出多孔”。现实中你就会发现,这种工程代码结构下的“组件”是由不同层上的不同的类来组合实现的,一部分落在了“服务”包里面,一部分则落在了“数据访问”包里面。

那么,如何才能让组件“力出一孔”呢,那就需要我们用特性来封装代码,而不是用层来封装了,组件应该要大声的喊出来,它是跟业务领域相关的

按照特性封装代码,就是类似下面这个图上所展示的。

图片
图片

当看到这个图示的代码结构的时候,熟悉DDD的同学估计就有一种豁然的感觉了,这不就是按领域来设计的么,没错,就是按照业务领域,这也就是刚才我们说的,组件要喊出跟业务领域相关的内容的原因。

这就是按层封装代码和按业务领域特性来封装代码的区别,按层封装,尽管可以清晰每一层的职责,但是代码结构却从未反映出我们从架构的角度看这个系统时考虑的抽象

如果你的软件架构图喊出了跟业务领域相关的东西(也应如此),这也会反映在你的代码里。

另外,评判一个组件的好坏和评判一个类的好坏,使用的标准基本是一样的,比如高内聚、低耦合,有良好定义的公共接口,有良好的封装特性等等。

以组件的方式或者是围绕组件,来设计一个软件架构,可能不是”唯一正确的方式“,但是,如果你一旦确定采用组件的设计思想,那么你的架构设计和编码之间,要确保是能够映射上的

也就是不要像我们开头说的那样,墙上的架构图是一个样,实际的代码工程又是一个样。如果,你对着自己的代码工程去解释自己的设计的时候,感觉很困难,那么这个时候就说明你需要改变点什么了,可能你的工程就没有喊出领域内的业务内容出来

记住,你的架构和代码之间一定要有相互的映射,通过代码能反映出你的架构,你的架构也可以通过代码来进行描述。

把软件架构图带回到现实,不要把它挂在墙上

到这里,有的人可能会走一个极端。

既然,软件架构设计和代码之间有可能会产生脱节的情况发生,那么我们走敏捷好了,不设计,直接干代码不就可以了吗。

我要告诉你的是,敏捷开发并没有让你这么干,敏捷也没说不要设计,甚至更没有说不需要文档。

与敏捷对立的不是架构设计,而是大型预先设计

好的,全都要

性能,必须要快;

安全性,系统必须保证安全;

可用性,系统的运行时间要达到100%;

当你跟产品经理或者客户聊到类似这样需求的时候,你肯定会得到这样的答案。

“100%”

“24/7/365”

“好的,全都要”

真的,必须全都要吗。

他们真的需要这样的可用性级别么,比如,一个5W用户访问量的系统,真的需要365天,每周7天,每天24小时都要保持具备提供服务的能力吗。

记住这一点,如果问人们是否需要一个东西,无疑我们都知道他们会说“是的”。

所以,当我们跟产品经理沟通需求的时候,就不能那样问,跟用户沟通需求的时候,也不能那样问,就要换种方式。

你应该这么问他。

系统平均应该支持多少并发的用户?

高峰时段发生在什么时候,持续多长时间?

多长的相应时间是可以接受的?

系统的各个功能部分都是这样,还是只是针对特定的功能要求这样?

为了保护系统安全,我们真的需要对数据加密码,添加访问权限是否就足够了呢?

要考虑成本进来,“全都要”就一定要多付出成本,时间上的,资金上的,人员上的都可能会涉及到。

比如,有个客户,想要开发一个系统软件,他们找到了你。

作为一名有经验的架构师,你应该这样跟客户沟通。

“你需要一个正常运行时间为100%的系统。构建这个系统必须通过大量冗余来消除每一个故障点,我们所有的花费都需要翻一番,外加很多自动故障转移工程的工作。这个成本大概是100万。或者我们可以为你构建一个简单一些的系统,必须告诫你,某些组件可能需要进行监测,发生故障时,需要手动重启,这样的成本大概是10万。您需要哪一种呢?“

要学会估算

在日常实际开发工作中,一名程序员免不了会经常跟产品经理、项目经理以及周围的同事、领导等去说一个功能的开发完成时间、成本等资源评估。

有一个非常经典的对话:

产品经理:要开发xxx功能,你预计需要多少时间吗?

程序员:一个月。

产品经理:时间也太长了吧!我们只有一个星期的时间。

程序员:我至少需要三个星期。

产品经理:我期望两个星期开发完成。

程序员:成交!

虽然最后谈妥了,但这名程序员真的可以在两个星期之内能开发完成所有功能吗,真的是做了合理的估算了吗,其实,估算出来的不仅仅是简单的一个时间,而是一种承诺

程序员是要对这个”估算“的结果负责任的。

所以,在这里,我们就要明确三个定义:估算、目标、承诺。

估算,就是对工期、质量、价值做出的近似计算和判断。

目标,就是项目要达成的业务目标的陈述,比如,上线后要达到多少用户使用,性能要求多少等等。

承诺,就是答应在某个时间或者某个事件发生的时候,提交符合某个质量水平的指定功能。

在一个项目刚开始,或者一个功能刚开始的时候,目标和承诺都要给予合理的估算。

软件估算的首要用途不是为了预测一个项目的产出成果,而是为了测定一个项目的目标是否足够现实,从而使项目能处于控制之下实现这些目标。

因此,程序员要学会进行估算。

常用的估算方法,如果学过PMP等项目管理知识的同学,一般都会熟悉这样几种方式:

自上而下的估算方法

这是一种专家判断的方法 ,它所使用的数据都是来自于历史的经验值。

自下而上的估算方法

这种方法是把项目拆分成不同的活动,然后对单个活动或工作包的成本做具体、细致的估算,再把所有单个活动的成本向上汇总,就可以估算出完成项目所需要的总体成本。

三点估算方法

我们最常用的估算方法,还是 三点估算法。

在三点估算中,有三个最常用的值,分别是最乐观的估计(a)、最有可能的估计(m)、最悲观的估计(b)。

把这三个数值进行加权平均计算,用最乐观成本加上最悲观成本,再加上4倍的最可能成本,然后除以6,就会得到我们的估算值。

图片
图片

既然,谈到了学习,我再谈点个人的经历,当我十多年前考完PMP的时候,我突然意识到,那是我离开校园以后,重新再一次参加的真正意义上的考试。

也是在那一刻开始,我更意识到,我,还是需要,真正意义上的持续学习的。

前不久,刚读完《人生由我》这本书,马斯克的妈妈写的,里面有这么一段描述。

在营养学领域在营养学领域,由于我一直在坚持学习,我对自己的专业知识非常有信心。为了保住我的营养师认证资格,每五年我会参加七十五次、每次耗时一小时的考试,而且我每天都会阅读新的研究文献。

注意,这个数字,5年75次,比硅谷钢铁侠埃隆·马斯克更酷的硬核母亲。

当然,我在这里也不是要引导大家一定要考个什么证,学个什么班,我想表达的是,把学习当成一种习惯

没有完美的线性扩展

你正在为一个系统的性能做架构扩展设计,那么,如果有一个方案,可以让服务器数量翻倍的时候,整个系统的吞吐量也能翻倍,这个时候,你的设计就实现了一个完美的线性扩展。

但是,在大多数情况下,完美的线性扩展很难达到。而,真实的情况是下面这幅图所表现的样子。

图片
图片

总是随着达到某一个点,这个点可以称之为拐点,吞吐量曲线随着资源的争夺加剧,逐渐地偏离了线性扩展。

这个点可能发生在资源使用率100%的时候,也可能发生在接近100%使用率的时候,这个时候比如排队比较频繁,还有的情况是磁盘的IO出现了瓶颈。

这个点之后,应用程序也会开始返回一些错误,比如Web服务器很可能会返回503”Service Unavaliable“,等等。

围绕这个点,在代码层面,我们还可以从以下几个方面来考虑。

你是否通过修改需求来提高性能?

你是否考虑通过修改程序的设计来提高性能?

你是否考虑通过修改类的设计来提高性能?

在考虑了上面那些条目之后,你还需要比如下面的一些调整的方法。

在开始调整代码之前,程序是完全正确的么?

在调整之前是否测量过性能瓶颈在什么地方?

是否记录了每一次修改所产生的效果?

另外,还有注意,现实生产环境中,绝大多数的程序都有那么一小部分代码耗费了绝大部分的运行时间。我们需要抓住这些小的部分。

恭喜你,又完成一次思考。

参考资料

《软件架构》、《代码大全》、《程序员应该知道的97件事》、https://zhuanlan.zhihu.com/p/108259898

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-08-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序架道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
项目管理
CODING 项目管理(CODING Project Management,CODING-PM)工具包含迭代管理、需求管理、任务管理、缺陷管理、文件/wiki 等功能,适用于研发团队进行项目管理或敏捷开发实践。结合敏捷研发理念,帮助您对产品进行迭代规划,让每个迭代中的需求、任务、缺陷无障碍沟通流转, 让项目开发过程风险可控,达到可持续性快速迭代。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档