饭局与人情

最近家里出了点事,然后老婆就找了朋友A帮忙,朋友A又找了他的朋友B帮忙。最后问题也就解决了。完事后,我老婆想着人家帮了忙,是不是该请A和B一起吃顿饭。只是A就一直推托吃饭这事。 恰巧最近也在看费孝通的《乡土中国》,里面就有讲人情这方面的。反正最近也闲,就对这事多想了想。饭局在中国可算非常常见,朋友间、同事间、家人亲戚间、生意上等等到处可见。这些情况的却别是什么呢? 朋友们一起组个饭局,这是最常见的。和朋友吃饭,无非都是在叙旧、调侃、聊天,很多也是也伴随着其他一些活动,如郊游、逛街,或者单纯就是为了一起吃一顿。朋友间的饭局,更多就是在培养相互的感情。这感情并非人情,而是真正的友情。为什么说一起同过窗、蹲过放、扛过枪的友情是最深的。那种环境下,天天在一起,一起吃饭、一起睡觉,海吹糊聊,相互间利益瓜葛又少,心理防线就低,这样就很容易增进感情。那朋友间的饭局也基本类似,无非就是为了常见个面,聊聊最近情况,吐吐槽,闺蜜、兄弟还能吐吐苦水。 同事间的饭局和朋友间的就有些不同。先说同事和朋友的差别。真正的朋友并无利益瓜葛,有利益瓜葛要成为好友的很难。同事间,存在竞争,也存在利益瓜葛,虽然天天一起,聊天机会也比朋友多,但是感情上依然无法和朋友比。那当然也有很多从同事变为好友的,那是感情积累到一定程度了。同事的饭局更多的像是例行公事,为了工作,需要和他们熟识,那饭局就是最好的熟识方法。这饭局也能增进感情,到一定程度也可以成为朋友。只是同事的感情淡的太快,究其原因,职场上无法交心的缘故吧。 正儿八经的商务饭局呢,我没怎么参加过,就个人理解,那只是一种过场。还是要说那种办事的饭局,吃饭的目的就是为了促成一件事,这里面就慢慢的人情。饭局里人情,但人情不是在饭局中,而是在办的事上。我给你一次方便,你给我一次人情,在这有来有往中,人情就一点点多了起来。人情是债,而且还是一个剪不断理还乱的债。 回到自己的事上,老婆找A帮忙,那就是老婆欠了A的人情,A找B帮忙,那就是A欠了B人情。这时我们要请吃饭,那这个饭局的目的就不明确,一不办事,二谈不上增进感情。而且通过A认识B,实际上A又需要欠B一个人情,原因是A给B介绍我们,这种搭人脉的也算一个人情债。说是为了答谢帮忙的饭局,结果变成又一次欠人情的饭局。怪不得A并不愿意去促成这样的饭局。 人情真是个微妙的东西。只能说深深的刻画在了中国文化中。在一个相互熟识的社会中,人情相当于货币。即使是现代商业社会下重契约精神,人情依然有着强大的力量。

August 23, 2023

我对数字化转型的理解

换了一份新工作,开始投身企业数字化转型的领域。对这个领域,我只能算是一个新手。为了工作,恶补了不少知识。看书、看博客、看各种课程,总算有了一点点理解。 作为一名技术人员,很容易被“数字化”三个字欺骗,把它与之前企业“信息化”做联想,然后觉得“数字化转型”也可能是提升一波企业的各种业务系统。而且看很多资料,也是介绍各种技术的,从架构到大数据,从AI到智能决策。很容易让人只从一面来看待数字化转型。 很多人把企业数字化视为第四次工业革命的一部分。那回顾下前三次工业革命,看看能不能找出点什么。 第一次工业革命时,已经有大量农民进入城市变为工人,在工厂中通过出卖劳动力换取报酬。随后一些关键技术被发明,如蒸汽机、飞梭、、纺纱机、蒸汽火车等,使得工厂使用机械替代原本工人手工的劳动。这也使得那些从农民转变而来的工人失去了生计。 第二次工业革命是以电灯的发明为标志,石油作为能源使用。工厂将生产集中,劳动分工使得工人根据生产力。随着掌握专业知识的人越来越多,中产阶级开始崛起。 第三次工业革命又称第三次科技革命,自动化的计算机提升了生产力,核技术提供了超过石油的发电效率。科学技术推动生产力的发展,转化为直接生产力的速度加快,也改变提高劳动生产率的方法。同时工厂效率提高释放劳动力进入服务业,第三产业比重上升。人们衣食住行等日常生活发生变革。(来自维基百科) 个人理解上,每次革命都是科技在推动,每一次也都在改变工人的生产方式。从机械式重复劳动到专门化劳动分工,从文盲工人到专业知识中产。这个过程中,对工人的知识和技能水平要求越来越高,而那些纯体力或重复性工作一步一步被科学技术的产物所取代。同时人作为昂贵的资源,减少对人的依赖也是一直的趋势。 再回来看企业数字化转型,依然是要求工人的知识和技术水平进一步提升,淘汰一批跟不上时代,思维无法转换的,不管是从管理层到普通员工都是如此。另外,使用人工智能以减低人的不确定性因素,也减少了对人力资源的依赖。可预见不久的未来,由于自动化和智能化的提升,从事日常运营和管理的人越来越少,更多的转向决策、创新等工作。 对IT技术人员来说,数字化转型更多的是给了一个额外的就业选择,不过人才需求应该没法抵得过现在裁员节奏。 以上是我的个人浅见。

August 17, 2023

能力和平台

虽然做了十几年研发,听了好多关于甲方和乙方的事,不过一直也没机会当任何一方。最近有幸做了一次甲方,参加了和乙方的讨论会。乙方是做SaaS版CRM,我们甲方的需求是希望将一些招租信息维护在CRM中,然后能以H5形式展示并分享给客户。对乙方来说这个功能需要定制化开发,就报了个百来天的工时。甲方的领导听了就很不乐意,认为一个简单功能还要这么多工时。作为一名技术人员,我自然知道这工时中的水分,这是领导都发话了,我说和不说都没啥区别。 这里不讨论工时水不水的问题,主要看下乙方的态度。合同没签,生意还在谈,报这么高工时明显不利于谈判。那难道是乙方没有合同的想法?肯定不是,没有哪个公司、哪个业务员不愿意赚钱的。我能理解的是,报高工时的目的只是不愿意做定制化开发,但产品还是想卖的。理解这个之前,我们先聊聊传统的办公软件。 我接触过不少的办公软件,传统的面向企业的办公软件,为了满足企业的各种需求,都是做定制化开发的。软件公司卖软件是一次性交易,后续无法再靠软件在同一个客户身上赚钱。软件定制化开发则是作为维护服务,收取客户维护费。但为了做定制化开发,就需要有大量的外围技术人员去做支持。这种模式自然能对需求的适配性更高,但开发成本也高。 对于SaaS模式,软件公司就变成售卖服务。这种云端产品,如果做大量定制化开发,对自己的产品来说是很不利的。所以很多都是做标准化,做平台化。平台化可以利用自身能力,让客户再有限的范围能做扩展。这种模式下,无法像定制化开发那样高度适配需求,但是降低了维护成本,让团队集中力量完善自身产品。所以说,乙方努力做自己的产品,打造平台,并不想做一些定制化开发工作。 说了乙方,再说说甲方。CRM是一款客户管理软件,它不承担企业的业务能力。甲方把管理招租信息的功能放在CRM中,实际已经让CRM系统去做业务工作。这样的问题,将来如果想更换服务提供商就很麻烦了。自己将自己与提供商绑定了。这种招租信息管理,应该是企业的业务能力,企业应该沉淀这种能力。如果自身有这样的能力,只需要通过CRM的平台,把能力接入进去就行,免去了定制化开发的费用,企业自身业务也更强健。

August 14, 2023

多机房自动化部署

之前入职了一家小公司,接了一个任务,实现多机房的自动化部署。 大致的情况如下: 公司产品主要面向政府,产品大部分都部署政府的机房中; 有一套jinkens,但是只能实现公司自己机房的部署; 现在外部机房的部署要么靠开发登上去后手动传包部署,要么由运维代为操作; 政府机房连接困难,VPN+二次验证+堡垒机+SSH,同时也不允许开放公网入口; 并没有采用任何云原生技术或容器技术。 从上述情况看,就VPN+二次验证这一点,基本毙掉了大部分互联网公司的方案。网上能看到的方案,无论大厂还是小厂的,单机房还是多机房多活,基本都是自己机房,可控权限高。采用这些方案的话,就要设法实现VPN+二次验证的自动化。面对不同政府机房不同VPN,这条路并不好走。 我没有DevOps开发经验,对于运维自动化也了解很少,只能找了些工具作为参考。最后决定模仿SaltStack,做一个C/S结构的发布平台。在服务端,主要是流程控制,从发布计划到单次发布作业,流程标准化、可追溯、可视化。客户端采用轮询方式,主动去服务端获取发布作业,然后执行相关的部署工作。 主动的轮询,客户端主动连接服务器,而不是服务器去连接客户端,这样政府机房服务器并不需要开放端口给外部使用。客户端通过公网访问服务端,也避开了VPN这一层。和SaltStack不同的是,我们的客户端在一个机房之部署一个,有一个客户端负载整个机房的部署任务。也是因为政府机房每台服务器都开放公网访问。客户端可以通过SSH连接每一台同机房服务器,类似于Ansible。C/S结构还有一个好处是以根据不同环境来做各种定制客户端,避免了服务端去适配。 基本框架订好了,剩下的就是细节问题。应用部署文件需要传输,同时最近的启动参数、配置文件等都需要一并传输过去。为了实现回滚,还需要有一套备份机制。最后还要对应用状态做检查,确定部署是否成功。 安全问题是一个坎,毕竟需要走公网,涉及数据传输,安全性就要求很高。有些对安全要求严格的政府机构可能就不允许这样的方案。 我没等到这个方案落地就离开了这家公司,所以后面无法在具体实现上跟进了。这里只算是记录了初步设想。

August 3, 2023

找工作

快35岁那会,对自己工作依然很乐观,毕竟那会互联网行业也蒸蒸日上。加之所在公司也还不错,所以就没有什么想法出去找工作。然后新冠来了,有严重拖延症的我,把换工作这事就一拖再拖。直到所谓的“互联网寒冬”来临,公司开始不断裁员。这才意识到,多年多年的安稳生活就要结束了。 4月份,选择了自愿被裁。一是公司的现状来看,留下也只是继续等待被裁而已;二是在这家公司工作了近8年,现在还能拿一笔丰厚的补偿金;三是相信自己能很快找到一份工作。5月开始就正式成为无业游民,加入了求职大军。原本信心满满,只是一次一次的“拒绝”和“等待”,让我知道了现实的残酷。 虽然最后找到了工作,不过回想这个过程,却让人心里难受。曾经不在乎那个“35岁”,现在成了最大的痛。曾几何时,网上到处都是说程序员过35就面临转折,我自是不信。但是一次一次投递简历,一次一次没有任何回音后,我就清醒了。简历真就卡在了35岁这条上。另外一个问题就是,多面没参加过面试,完全不知道面试会问些什么,需要准备什么。能做的只是网上找各种面试资料。这种无头绪的准备,也让我错失了难得的几次面试机会。 还好我天生乐天派,能一直保持一个乐观的心态,不至于让自己陷入焦虑之中。给自己一句话:“事已至此,努力向前才是最重要的”。懊悔往昔,担忧未来,这些都无法起到任何帮助。 期间联系了很多同行的朋友和过去的同事,沟通感情是次要,主要是看能不能帮内推下。很多公司对内推还是比较重视的。没个优先权么,也至少会正眼看一下简历。果然内推给面试机会的远比瞎投简历的多多了。在此感谢那些帮我推内的朋友们。虽然最后也没一个靠内推拿到offer的,但那都是我自己能力不行,白白错失良机。 说到面试,我对面试的印象还停留在7、8年前。虽然工作后也有作为面试官的机会,不过面试的都是初中级的开发,主要还是问问写八股文,简单聊聊项目经验。自己作为被面试者,那感觉还是天差地别的。这期间的面试次数也不多,而且形式还不尽相同。有一个劲儿问技术问题的,有结合项目经历问技术问题的,也有只深入问项目经历而不问技术的,还有直接给问题让出方案的。林林总总,搞得我都不知道怎么准备。这时候就真体现知识储备量了。不管是技术知识,还有平时看的闲散文章上各种经验总结,能结合自己工作说个事的,都可以拿出来聊一下。所以平常没事多看看技术含量高文章也是有价值的。 新工作并不如意,一则小公司很不稳定,今天看你是人才,明天就嫌弃你薪资贵,把你扫地出门。二是业务都是我以前做过的,毫无新鲜感,工作属于一眼看到头类型,不会有晋身机会,技术也没什么可看的。马上四十的人了,职业生涯基本都进入下半场,虽一事无成但也要考虑下职业规划。之前的业务经验可以为现在找工作带来一定的优势,特别我这种还在这个行业算数一数二的公司工作的,可以拿业务经验去忽悠小公司面试官。但是之前公司都成这样了,也证明这个行业并不好混,现在是看不到任何太光明的前景。是重操旧业还是勇敢地迈向另一个行业,需要深思了。 就到这里,后面估计又是骑驴找马的生活。不知道到退休前还要经历几次求职。

July 28, 2023

关于项目提速的思考

这几天在看日剧《重启人生》,第四集中,女主角为了帮助他高中老师,让剧组加速拍摄的桥段。大致剧情是,女主已经是第三世了,为了让自己不投胎变成动物,反复重新开始人生。这一世她做了剧组的工作人员。根据前世记忆,这天她高中老师有难,她需要在21点多赶到地铁站,可是剧组当天的行程要到21点30分结束。除非能提前两个小时结束,不然来不及救老师。于是,她决定提速当天的拍摄进程。当然,在主角光环的作用下,她硬生生让剧组提前了3个小时完成当前拍摄工作。虽然有编剧的扯淡和主角光环,但是,其中很多东西仍然值得多思考下。 我没在剧组工作过,所以对拍戏这是没任何概念。就只能说下在电视中看到的一些拍摄工作的情况。日程是串行的,也就是必须拍摄完一段,才能拍下一段;每段拍摄前需要确保布景、演员、化妆、摄影、灯光等都到位才行;部分演员(特别是重要的演员)都是在指定时间段到达的,并非一直在等待。了解情况后,来看看女主做了些什么事。 1、先让个别的人加快进度 通过个人人际关系,让少部分人先快起来。然后再传递进度变快的消息给其他人,让后面人跟进。剧中,化妆师是她同学,请化妆师加快后,她就回头告诉布景等,说明演员就绪的时间。后续人员看到前面准确就绪时间后,也会相应调整自己的节奏。一环带动另一环,从而让整个进度一点一点提前。 这点的延伸,工作中,很多人都觉得别人会是任务瓶颈,自己并没有必要提前开始或加快完成。因为即使自己完成了,那边也无法跟上。但当大家都这么想的时候,就变成了相互间等待的情况。最后就是都在按工期走。 2、找出可并行事项 一天七八个拍摄任务中,有一个是演员手部特写。这个需要拍摄条件相对容易满足,加之演员本在拍摄完其他内容后,正在休息,可以利用拍摄的特殊性和演员状态,将原本需要等待后面拍摄的工作并行完成。 3、让成员保持良好状态 状态越差,出错概率就越高,出错就要从来,很耽误时间。让成员处在一个良好的状态下,就能让拍摄变得更顺利。剧中,她会选择给剧组成员和演员们,送杯水或者饮料之类的。当然用这种方式就能保证他们状态,就有点扯了。 4、让全员都相信能提前完成任务 很多时候,成员么都不认为能提早完成工作,所以各自都按现有的计划进行,按部就班的工作着。这种状态下,加速几乎是不可能的。所以要让他们都意识到,整个项目已经加速,并且确是能实现这个目标。 5、关注瓶颈,提速瓶颈 瓶颈之所谓瓶颈,就是最能左右整个项目的进度的。如果不把瓶颈搞定,那加速几乎不可能加速。剧中最后一场的演员,因为只有最后一场戏要拍,按预期会在最后一场拍摄前到达,只要够化妆和服装的准备就行了。剧中,女主看完行程后就直接打电话给演员,请他提前来。 6、让关键人物、关键步骤提前就位 虽然关键人或物不一定是瓶颈,但是如果延迟或缺失了,那就会直接阻断整个项目进度。 7、了解队友,相信队友,发挥队友能力 剧中,一个场景中的布景设施坏了。如果换成之前,大家都会选择暂停拍摄,等待修好。特别是现在,他们有很多时间来抵消这个意外所造成的时间浪费。只是在情绪高涨的团队中,团队成员自发排除困难,让拍摄不延误。另一个剧情是,最有以为演员堵在路上,女主果断求助长期跑外景,对东京大大小小街道了如指掌的剧组司机,司机也很愿意给出方案。最后演员准时达到,大家皆大欢喜。 上面是根据剧情总结的内容。总结下来就是:提振信心、聚焦关键、动态规划。 动态规划这个,我之前的项目经历来说,项目的时间规划中,必然有预留应对容错的时间。不管项目经理也好,还是实际干活的成员,都不会估算出很紧凑的排期,多多少少都会预留点应对突发状况的时间。但是最后在没有突发状况时,由于后续排期已定,后面的人也不会提前,前面的人也会因为有充裕时间而放慢节奏。如果可以动态根据实际情况,反复调整排期,也能让项目加速。只是动态的调整必然会打乱其他项目的节奏。 话说《重启人生》这电视剧不错,值得一看。

June 26, 2023

DDD的思想的应用

我在上一篇说了下我在DDD实践过程中的一些想法。要长期实行DDD的话,领导的支持、人才的培养、领域专家的协助等,都是不可缺少的。很多情况下,我们都无法有这么好的条件。那是不是说,就没什么意义去学习领域驱动设计了呢。其实不然,且听我分析。 我本人兴趣广泛,喜欢东学一点,西学一点,偶尔捣鼓点小东西,自娱自乐下。但是对于一些枯燥的原理东西又不是特别感兴趣,这就导致了很多技术都是懂个皮毛,不深入。所以要往技术架构、技术专家发展就带来了一些困难,于是就想着往业务架构方向发展。只是网络上找了个遍,也很少介绍有关业务架构是能力怎么发展的书籍。后来想了想,业务专精的技术人员,因为受限于从事的行业业务,经验无法在其他行业通用。(这也是想往业务架构发展的技术人员一个要考虑的点。可能后续找工作会成问题。面试的一看是业务架构,偏向业务,要是和公司业务不符,可能直接PASS)。 后来接触了DDD后,了解了其背后的思想,才让我对业务分析这方面有了一定的进步。下面我就说说自己从DDD中学到的。 共识 业务专家不懂技术,技术不动业务,产品就作为了技术和专家中间的桥梁。可产品也有自身的问题,并非每一个产品都能对业务了如指掌,对技术的理解也止步于懂个大概。产品在传递一些信息和概念的时候,多少会参杂自己的理解,有的甚至是曲解。为此,DDD的做法是让专家、产品、技术一起参与项目,一起讨论。其中一个目的是能让项目成员都对业务中的一些定义、名词等达成共识。只有这样才能消除沟通带来的歧义,这也是对业务进一步分析的基础。 一个简单的例子,“订单”这个词不算陌生,但是在一个电商系统中出现“订单”字眼的地方很多,仓储系统、物流系统、交易系统、支付系统等。但是对于不同系统,具体应该是不同的领域,不同的上下文中,“订单”的概念是不同的,有些系统还会出现多种“订单”定义。比如,对于支付系统,就有支付订单和交易订单,而交易订单更多的只是一个与外部关联的值而已,支付订单才是它的业务核心。理清这些内容,建立统一语言,让团队对业务达成共识,这是DDD的思想之一。 从产品经理角度看业务 我很想说从领域专家的角度去看业务,不过这个确实很难做到的。 在了解DDD之前,我从没听过用户旅程、用户故事、事件风暴之类的名词,对产品经理如何分析业务也是一无所知。大部分开发基本都和我一样,对业务的理解都是来自现有代码和产品经理对业务的描述。代码本就是开发写的,而产品经理也不会把自己怎么分析业务的过程对开发说的很详细。这样,开发理解的业务就是很片面,很局限。当问及“某某接口是做什么的”这样的问题时,开发更多的回答就是,这个接口提供了什么样的功能,却无法回答上层的业务是如何的,接口在整个业务场景中的作用是什么。 要理解整个业务,就必须换个方式,换个角度去看业务。如果自己是产品经理,需要给开发讲解业务,能讲解清楚吗?如果自己从零开始分析、设计这款产品,又会怎么做?产品经理那些分析业务的方法自己是否可以学,可以用呢?只能说这样的转换是一个漫长过程,这找不到什么快速的学些方法,我自己还在慢慢摸索。也许有一天,不愿意做开发了,可以做一个懂技术的产品经理。 领域模型 开发不喜欢写文档,写出来的也不怎么靠谱。开发间通用的可能就是各种UML图和架构图这些。只是这些图都不能很好的反应业务,也是导致业务分析结果无法长时间留存和随业务发展而演进。 DDD需要产出领域模型,他是业务的抽象结合技术后的产物。他对开发更友好,虽然丢失了业务细节,但依然能很好反应业务。个人觉得,将领域模型作为整个迭代过程的中心,领域模型前是对业务需求的具体分析,确定领域模型后就是开发在它基础上做技术实现。领域模型也成为后续开发理解业务的一个起点。 从领域模型到代码模块 这个好像没啥好说的,到了实现这部,看的就是个人编码能力了。 DDD的学习,对技术的提升很有限,更多的是在提升对业务的分析能力。这个能力不局限于某一行业或领域,它是通用的。深入学习,以后怼产品、忽悠领导就全靠它了。

June 14, 2023

DDD实践杂谈

最近在找工作,深知自己没多少斤两,也只能苦刷八股文。不过在很多招聘的信息中看到了领域驱动设计这个关键词。刚好之前公司实践过这个,也许这个是可以在面试中吹吹的东西。于是乎就努力回想了下之前的经历,希望能整理出点有用的东西。 领域驱动设计,简称DDD,说它是设计思想也好,方法论也好,哲学也好,最后的目的就是让代码能更好反映业务,同时还能控制业务和系统的整体复杂度。其实吗,各种架构、模式、模型什么的,都是在控制复杂度,因为这些复杂就是生产效率的敌人。 以往,如果让我去梳理一个复杂的业务系统。我肯定在了解业务后,提供各种解决的技术方案,然后就是重构。等重构完,确实整个系统的代码会干净、整洁很多。讲得高大上一点,就是耦合度低了,内聚高了,接口设计更合理了,代码可读性也高了。可是当几个迭代版本后,就会发现,似乎有慢慢的回到之前的模样了。这里的两个重点就是,第一、我们的改造方案虽然是基于业务,但是更多还是基于技术角度思考;第二、我们的代码无法一直保持这个良好的状态。我们的工作就在迭代、重构、迭代,再重构的循环中。那如果不重构呢,对于那些还在高速增长的业务系统,忽视技术债务,最终也只会把开发拖入泥潭。 DDD的目标就是解决代码无法随业务模型同步调整的问题。通过维护一套领域模型,让代码随着这套模型一起演进。新的业务功能进入系统时候,需要先融入到这套模型中,才考虑代码的实现。 听上去,除了DDD理念中的统一语言、划分领域,以及一些花哨名词和概念外,并没有什么新花样。其实很多高级开发或架构师,都在做差不多的事情,分析业务,然后根据业务对系统架构和代码做调整。问题是,很多开发留下了最后系统调整的方案,却没有将分析业务的成果留存,或者留存了也没有在后续持续更新,更别说以业务模型作为开发设计的中心。DDD则在需求设计、业务分析、领域模型设计、代码实现等各阶段,提供了一套行之有效的方法。保证领域模型紧随业务变化,代码符合领域模型。 扯了那么多,还是谈谈之前的落地经历吧。说叫落地实践,实际就是摸着石头过河。翻遍了网上的资料,除了大牛那两本后后的书外,很难找到完整的落地方案。很多就介绍了个大概,也没有了啥后续。所以实践就变成了摸索。相对于战略设计,战术设计可能是开发最擅长的,只要在摸清业务,确定领域模型的前提下,战术设计完全可以有开发单方面完成。那战略设计就成为了实践中的重点。团队还是选择了事件风暴这种方式来分析业务。事实也证明“事件风暴”确实很有效果。从事件和用户旅程出发,能很快让开发了解完整的业务。同时挖掘业务流程中,一些不怎么被开发关注的内容。分析完成业务后,后续就是划分领域和上下文,以及模型设计等工作。这个过程也是反反复复的,毕竟对于复杂系统,很难一次性掌握。 DDD的好处,网上随便找一篇文章都能说出一堆来。只是对于落地的难处却说的比较少。我这里就说下过程中遇到的难点。 第一、领域专家难寻 DDD的要求就是和领域专家一起来梳理业务。我们团队刚好在一个比较传统的,或者说行业内业务很成熟的系统中实践DDD,加上公司确实有这方面资源,可以轻松和领域专家一起工作。同时开展DDD实践的另一个团队,那就没这么好运了。对于互联网行业,很多新兴的业务,都是靠着一群富有创新力的人才创造出来的。领域内并没有专家可以找,唯一对业务了解的恐怕就是产品经历了。这种情况下,分析业务就完全靠开发和产品自己对业务的理解了。还有就是领域专家是甲方的,也很难说动甲方参与设计和讨论,特别DDD的模式下,需要长期参与其中。 第二、老板或领导的意愿 很多领导或老板,脑袋一热,就要上DDD,可能并没有了解清楚。当时DDD实践是,就会无形中拖慢整个开发流程。毕竟,对核心业务的每一次调整,都要从需求开始,在业务层面梳理清楚。不像以往的上来就写代码的模式。那些头脑一热的领导,往往会被劝退。在没有上级的支持的情况下,DDD是很难维持的。特别处于长期工期紧张的团队。 第三、人才储备 系统不断的迭代,DDD也不是一锤子买卖。必须有人来负责管理,让团队可以持续进行。团队的其他成员也需要有能力,有意愿支持这种形式。特别是在工期压力大的团队,很可能团队选择逃避这种复杂的设计方式。这种情况下,核心成员的离开,很可能导致后续没有人能接手,从而放弃DDD。 第四、没标准,没最佳实践 网上很多都是说自己实践过,但是也没说持续多久,效果如何,哪些问题,怎么解决这些问题。更谈不上最佳实践了。而DDD本身是方法论、是思想,并没有对过程和产物做标准化定义,那不同团队设计出来的方案各不相同,这也导致了很多东西无法有效推广。 以上都是我个人的一点想法。本人经验有限,可能很多考虑不成熟的地方。

June 13, 2023

Zuul网关丢失鉴权信息问题

公司有个项目使用spring cloud全家桶。由zuul做入口,路由到各个业务系统。其中路由完成登陆鉴权。后来有一个业务系统需要用到这些登陆信息,所以希望路由这端将登陆的信息通过消息头的方式带到业务系统。 想想实现很简单,定义一个feign的拦截器,把登陆信息填到header中。不过中间遇到个小问题。统一的路由中将信息保持到了一个ThreadLocal中,拦截器会从这个ThreadLocal中取出数据。问题就出在这里,取到的数据是空的。其他地方也在使用这个ThreadLocal中的数据,并未发现问题,未读这个feign拦截器却不行。最奇怪的本地测试可以,跑测试环境就不行。 再三排查,也查了不少资料,最后看到有博客上提到差不多的问题,原因是Hystrix的策略导致的。Hystrix使用不同的线程完成工作,也就是说Hystrix的线程与Request不再同一个线程中。这样,基于ThreadLocal的一些功能都无法正常使用。后来再stackoverflow上找到了解决办法,连接。框架的开发者也知道这问题,所以提供了一套完整的解决方案。HystrixRequestContext和HystrixRequestVariableDefault就是用来解决这个跨线程时共享数据问题的。简单的说,放入HystrixRequestVariableDefault中的数据,不管是在Requst线程中,还是在Hystrix的线程中,都可以访问到。不过HystrixRequestVariableDefault必须在每一个请求开始的时候进行初始化,同时在请求结束收回收里面的数据。 方案有了,上代码,先实现一个mvc的拦截器,将ThreadLocal中的数据转到HystrixRequestVariableDefault中: public class HystrixContext { public static final String LOGIN_INFO_HEADER_KEY = "his-login-info"; public static final String TOKEN_HEADER_KEY = "token"; public static final HystrixRequestVariableDefault<LoginInfo> LOGIN_INFO = new HystrixRequestVariableDefault<>(); } try { if (!HystrixRequestContext.isCurrentThreadInitialized()) { HystrixRequestContext.initializeContext(); } LoginInfo loginInfo = convertLoginInf(request.getHeader(HystrixContext.LOGIN_INFO_HEADER_KEY)); LoginInfoUtil.setInfo(loginInfo); String token = request.getHeader(HystrixContext.TOKEN_HEADER_KEY); LoginInfoUtil.setToken(token); HystrixContext.LOGIN_INFO.set(LoginInfoUtil.getLoginInfo()); } catch (Exception e) { LOG.error("从头信息中获取数据失败", e); } 然后给feign加一个拦截器: try { if (!HystrixRequestContext.isCurrentThreadInitialized()) { HystrixRequestContext.initializeContext(); } LoginInfo loginInfo = HystrixContext.LOGIN_INFO.get(); if (loginInfo !...

June 28, 2019

Django2 Template 路径配置

前端时间在那django些个小网站,其中需要配置下template路径,按以前经验配置了下, TEMPLATE_DIRS = ( os.path.join(BASE_DIR, 'templates').replace('\\', '/'), ) 弄了半天也没成功。最后无奈去看了下官方文档,找到内容有限,不过可以确定的是TEMPLATE_DIRS这个配置项已经没有了。 然后谷歌了下,找到了新的配置方法: TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', # 这里,这个DIRS就是 'DIRS': [os.path.join(BASE_DIR, 'templates').replace('\\', '/'),], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] 这个方法在django 1.8以上到我现在的2.0.2有效。不保证以后版本依然有效。

March 22, 2018