DDD领域驱动设计批评文集
做强化自测题获得“软件方法建模师”称号
《软件方法》各章合集
(《你的医书是假的!》原文写于2023年8月,以系列文章方式发表,现合并成一篇文章)
一、说在前面
这两天在“ Thoughtworks洞见”公众号上看到一篇付施威的《DDD诊所——聚合过大综合症》。
相对于DDD圈子各种各样错误百出的玄学文章,这篇《DDD诊所》已经算是想要认真探讨问题的难得之作,说得粗俗一点——可以算是翔中的豆芽菜或金针菇了。
如果仅仅是自娱自乐的学习心得,只要不自吹“创新”、“棒棒哒”或被人热捧为“创新”、“棒棒哒”,我是不会去批评的-参见《“以炮换马”的DDD歪招是否可以作为起步》。
但这里作者要去当医生治疗病人了(虽然不收诊金),那就得好好说一说了。
其实我要批评的几点,在之前我写的《DDD领域驱动设计批评文集》序列文章中都提过(因此本文我会偷懒,放上大量我写过的文章的内容截图),这篇文章也不幸一一命中,这并非偶然。
从我开始写《DDD领域驱动设计批评-合集》序列文章,到现在已经有4年了,在这期间:
*没有人针对我写的文章内容做出反驳;
*有个别DDD粉丝嫌我气量狭窄,《潘老师,你的气度有点小了!》;
*有个别DDD圈子人士质疑我的动机,《批DDD不批马保国,说白了就是DDD影响生意了》、《回应张逸老师(一)圈子文化》;
*没有DDD圈子人士当面(包括线下和线上)对我恶语相向,都是很礼貌地叫我“潘老师”;
*【我推测】大多数DDD圈子人士没有稍为认真地扫一遍我写的文章;
*少数DDD圈子人士表现出很有诚意和我讨论和向我学习建模。我说,如果乐意学习或和我讨论,可以先看书和做题,我出了几百道扫码自测题,做对大半后,如果有问题可以再讨论——理由参见:
《软件方法》分步改进指南(2024版)
《软件方法》自测题为什么不直接给出答案
漫画版《软件方法》、奶头乐和高数买菜;
*但是(往往真正要说的藏在这里)!目前为止,我还没有发现DDD圈子有人按照我的建议认真去做——这个我看得出来的。
我描述的上述若干现象,看起来有点诡异甚至互相矛盾,对吧?可以看我写的《小甜甜和牛夫人?》,理解了这个圈子的创新观和风气,就不觉得诡异了。
(可能有的读者会说,你自我感觉怎么这么好?大家都很忙,你阿猫阿狗随便写点什么,人家凭什么要认真看,认真学习或认真反驳?问题在于,至少在这一点点上,我不是阿猫阿狗啊。毕竟圈子吹捧的这个东西,我还是最早引进的人之一,参见《小甜甜和牛夫人?》)
**********
下面,我按照《DDD诊所》的文章结构依次评点,其中最严厉的批评出现在【治疗建议】部分。
二、【患者主诉】评点
《DDD诊所》的这部分罗列了系统的一些功能以及存在的问题。
(1)罗列功能可以加上(或改成)业务序列图。
以下例子可供参考。
2022年,《DDD诊所》作者所在公司Thoughtworks的另一位同事曾来上我的课,并提供了一个“企业持续交付流水线平台”的案例项目在课上剖析,现在又看到《DDD诊所》这篇文章里也提到类似项目,不知道两者之间有没有关系。
以下几张图就是当时我在课上和学员讨论后针对“企业持续交付流水线平台”案例画的第一个迭代的现状业务序列图、改进后业务序列图和系统用例图。
图1 现状业务序列图
图2 改进后的业务序列图
图3 系统用例图
以上图仅在课上短时间内完成,仅供参考。
(2)类图很可能逃避了最难也最有价值的规则部分
接下来,《DDD诊所》给出了一张类图:
图4 《DDD诊所》中的类图
能认认真真画一张类图,光是这一点就已经压倒很多DDD文章。
很多DDD文章列出两三个类,甚至有的就一个类,然后就开始往上批量刷**Service、**Repository。《DDD诊所》所给出的类图中,类的个数远远超越了那些文章,而且我仔细看了类图,表示法上也基本没有什么问题。
可能存在的问题是内容的问题:规则没有显式建模。
类图右侧的“触发规则”、“阶段质量门禁项”的比较规则,这些“规则”不是独立的,它们隐藏在类以及关系之中,应该在类图上显式表达。
很多人经常犯的错误就是,轻飘飘地用一个类“**规则”搞定,似乎这样做之后“**规则”就会从天上掉下来。这其实是逃避了问题,因为封装“**规则”相关的知识,很可能就是你的系统存在的理由。
(如果“**规则”里面的逻辑已经由第三方搞定,那么必定还会有另外一个“**规则”的逻辑是你的系统存在的理由,钱哪里是那么好挣的?)
如果一个类的名称是以下面这些结尾:er、or、器、策略、Strategy、Policy、规则、Rule、算法、Algorithm……一定要警惕,有可能这种类是逃避了真正问题的废话。
关于这个内容,我之前的文章《软件开发团队的脓包》里面的“废话迷”部分可以参考:
图5 《软件开发团队的脓包》的“废话迷”部分截图
我写的《软件方法》下册第8章也可以参考:
图6 《软件方法》第8章截图
上面提到的“企业持续交付流水线平台”,我当时在课上画过一个类图,也可以作为参考。灰色部分表达了规则。
图7 我在课上画的类图
规则表达清楚了,剩下的就相对简单了,无非是在规则上玩游戏,把结果记录下来。不过,我们看到的很多建模者,能力仅能达到“把结果记录下来”,很难做到“显式描述规则”。
而“显式描述规则”的缺失,往往会带来另一个错误:事物规格和事物不分。
例如,图4中,“阶段”、“步骤”中的“参数”指的是什么?是名称还是值?
项目的哪一个阶段(步骤)应该有什么样的参数?这是一个知识。
某个具体项目的某个阶段(步骤)什么时间发生的,具体参数值是多少?这是另一个知识。
这两个知识变化频率不一样,不能用一个概念覆盖。
还有像这个:
图8 《DDD诊所》中的经“医生”诊断后的类图
图中这样一写“下一个步骤是阶段的步骤列表中的下一个”就完了?然后好事就从天上掉下来了?步骤的顺序在哪里呢?这可不是在“步骤”中加个“序号”属性或者在“步骤”上建一个自反关联就能解决的。
一个阶段有哪些步骤?它们之间的顺序如何?这是一个知识。
张三的项目当前到了某某阶段的某某步骤,这是另一个知识。
这两个知识不分开,必定会导致大量冗余的数据(即对象的属性值)。
三、【诊断】评点
这一部分描述了使用聚合/组合时要警惕的问题。这个部分的问题主要是造词,“***综合症”之类。
另外,“聚合根”就是一个伪创新,这个内容我在《DDD话语“聚合”中的伪创新(1)》、《DDD话语“聚合”中的伪创新(2)》中已经写过,不是本文批评的重点。
四、【治疗建议】评点
这是本文批评的重点。
(1)《DDD诊所》引用的文字存在严重的翻译错误。
为了“治疗”,《DDD诊所》先摘了一段《领域驱动设计》中译本的文字:
图9 《DDD诊所》截图
可以看出,《DDD诊所》的作者所摘的文字应该来自人民邮电出版社2016年的译本。
这个译本翻译得很糟糕!
《DDD诊所》所摘的内容,原文并不是在一起的,而是分离的两段话。我在文章《猴子掰玉米?比较不同版《领域驱动设计》说“不变式”和“聚合”》中针对第二段译文做了评价。
图10 《猴子掰玉米?比较不同版《领域驱动设计》说“不变式”和“聚合”》截图
图10中的重点是:不变式是类的不变式,是类所封装的逻辑,而不是说有个孤立的“不变式”,然后几个类去满足它。
而这一点,《DDD诊所》的作者应该不了解,例如,他在文章里说“订单与订单行之间存在固定规则”:
图11 《DDD诊所》截图
有趣的是,《DDD诊所》的作者还引了维基百科作为佐证:
图12 《DDD诊所》所引用的维基百科
问题是,我们讨论的是面向对象语境下的不变式(部分历史可参见《“**领域驱动设计”的这个不变式是不是多余》),面向对象语境下,所有的逻辑都封装在类里面。
《DDD诊所》里用的方法应该是(或者自以为是)面向对象方法吧?如果不是面向对象,而是作者刚创新的“领域驱动设计大模型人工智能数智化敏捷方法”,那以下文字就当我没说。
不变式所表达的本来就是一段规则,你爱怎么组织都可以。面向对象的组织,就是把这些规则按类组织,从而把逻辑封装在类中。
例如,越南某公司有这么一些规则:
员工年龄不得超过性别的年龄上限,例如男性45,女性50。
还有,部门中男员工人数不得超过女员工人数的2倍。
可以分为两个类的不变式:
图13 “员工”的不变式和“部门”的不变式
可以看到,不变式是放在类上面的,并不是像图8、图16和图18一样,放在类关系上。
我们还可以观察到,“员工”的直接或间接属性有:年龄、员工性别.年龄上限、员工性别.名称。
要是这些属性的值的组合没有任何约束(例如年龄46,性别男),那么系统的复杂度会大大降低——可惜,现实中不是这样(这正是图10中Bjarne Stroustrup所强调的)。
“员工”的不变式正是这些属性之间的约束的一个表达式——并不是像图8那样意淫式地随便写句话;
(不变式如何表达,参见《不变式有标准或者语法吗》)
同样,“部门”的直接和间接属性,除了“员工”集合之外,还包括上面列出的“员工”的直接或间接属性,而“部门”的不变式正是这些属性之间的约束的一个表达式——并不是像图8那样意淫式地随便写句话。
那可不可以把“员工”和“部门”的关联方向倒过来?可以的。这时,原来加在“员工”上的不变式应该不用修改,但原来加在“部门”上的不变式就要挪到员工上(因为“部门”访问不到刚才那些属性了),而且表达式也要修改——肯定能表达,无非是集合运算,区别在于更直接还是更弯弯绕而已。
从这一点也可以看出,到底是“员工”知道“部门”合适,还是“部门”知道“员工”更合适?不变式可以作为参考依据之一。
要提醒的是,不变式仅仅是表达逻辑的选择之一,而且也仅能表达部分逻辑。
DDD圈子为什么独独吹捧这个呢?哦,因为《领域驱动设计》提到了它,更关键的是,这个圈子是一个封闭的互吹互捧的圈子。
(2)问题更大的是,《DDD诊所》的作者对译文的糟糕没有敏感性。
最简单的一点,Invariant译为“固定规则”的,【我见过的】是独此一家!
列举几本有一定水平的书(说的是原著),有译作“不变式”的:
图14 Meilir Page-Jones《UML面向对象设计基础》(人民邮电出版社)截图
有译作“不变量”的:
图15 Ian Graham《面向对象方法原理与实践(原书第3版)》(机械工业出版社)截图
以上所列,都不是UMLChina译,以免被认为故意挑选。
《DDD诊所》的作者居然不觉得有违和感,是因为只看过《领域驱动设计》的这个译本,而没有看过其他书?
如果《DDD诊所》的作者手上资源有限,例如,没有别的译本,没有英文原文,没看过其他书……那应该想办法去丰富自己的资源,等学习好了再给人看病。
当然,如果创新观和我在《小甜甜和牛夫人?》中评论的创新观一样,那我就不再对此说什么了。
(3)问题最大的,《DDD诊所》的作者缺乏对“废话”的基本敏感。
不了解或误解(1)中我说的不变式的知识,这个好说,花时间学习就是。
下面这个才是我认为最严重的:
图16 《DDD诊所》截图
《DDD诊所》的作者把“A更新的时候,会不会引起B的某个属性的更新”,“如果两个实体暂时不一致,是否会导致难以承受的业务后果”、“订单的总价等于订单行的总价之和”看作不变式要表达的内容。
——这是不变式吗?这是冗余吧?
像图中“订单的总价等于订单行的总价之和”,如果这个公式被严格遵守,那么“订单”类的“总价”属性在逻辑上就是冗余的,应该删掉。
既然“订单”的“总价”属性没了,图16上所标的不变式也就不存在了。
那怎样才是“订单”需要表达的不变式呢,我举下面的例子供参考:
图17 合理的不变式
“订单”类中不变式的意思是:
任何一个订单对象,其订单项集合中不存在这样的订单项,本订单的配送地址所属区域就在该订单项所购商品的禁售区域内。
例如,某款“iPhone**”不能卖往长三角地区,如果订单的配送地址是“南京市****”,那么订单里面是不能存在购买“iPhone**”的订单项的。
注意,我给出的图13、图17等类图,上面的信息没有冗余。
**********
面对冗余,建模者毫无察觉,反而甘之如饴,这说明建模者缺乏基本的建模训练,这已经和面向对象或不变式没关系,即使辩解说“我用的不是面向对象,用的是领域驱动设计大模型人工智能数智化敏捷方法”也一样的。
我在另一篇文章《“**领域驱动设计”的这个不变式是不是多余》中也批评了类似的“不变式”废话:
图18 《“**领域驱动设计”的这个不变式是不是多余》截图
难怪,我一直“赞扬”很多DDD伪创新:投资少、见效快、产量高、门槛低、仪式感十足,它们确实迎合了某些开发人员的需要。
很可能有人会以“性能”为理由为自己的能力缺乏辩护。
是的,如果在实现时确实由于需要频繁计算订单总价,导致出现不可调和的性能问题,可以添加上冗余属性(用数据库语言就是冗余字段)“总价”,甚至添加冗余类(用数据库语言就是冗余表),但这属于通过添加冗余来缓解性能问题的实现套路,和具体的领域知识无关。
关于“性能”这块遮羞布,可以参考《软件方法》中的内容。
图19 《软件方法》“性能”截图1
图20 《软件方法》“性能”截图2
*****以下是续文*****
我写了一篇文章,批评付施威的《DDD诊所——聚合过大综合症》(以下简称《DDD诊所》),文章是《你的医书是假的!批评付施威的《DDD诊所——聚合过大综合症》》(以下简称《你的医书是假的》)。
一、《你的医书是假的》关键内容
《DDD诊所》说,下面这个是不变式:
图1 《DDD诊所》截图
我在《你的医书是假的》中提出以下批评:
(1)不变式是类的不变式。《DDD诊所》作者把它放在关系上是不对的,说明该作者没有理解不变式。
(2)《DDD诊所》作者引用的《领域驱动设计》译文的翻译很糟糕(参见《猴子掰玉米?比较不同版《领域驱动设计》说“不变式”和“聚合”》),关键内容的意思译反了,而《DDD诊所》作者并无察觉,反而整段引用作为依据。
(3)不变式不是用来描述像图中的“订单总价=sum(订单行总价)”这样的内容的。如果这样的约束被严格遵守,说明“订单”的“总价”属性在逻辑上是冗余的,应该删掉。既然“总价”属性没了,图1的所谓“不变式”自然也就没有了。
也就是说,改变订单属性值(包括加/删订单行以及其他操作)的时候,不需要判断某个含有“总价”属性的表达式是否为真——实际上也没法判断,“总价”属性都没有了嘛。
接下来,我再针对图1做进一步的阐述,帮助进一步理解不变式,并评点在《你的医书是假的》文章下面的留言。
二、等号和赋值号没搞混吧?
不变式是一个布尔表达式。
我在这里提这一点,到底是什么意思呢?
意思是:
如果发现有“不变式”表示为相等关系的表达式,那就要警惕一下,建模人员是不是把“=”当成赋值来理解了。
例如,图1的式子“订单总价=sum(订单行总价)”,有可能就会被误解成“把订单项的价钱之和赋值给订单总价以同步这两边的值”。
读者可以注意到,我在《你的医书是假的》画的图例中,没有相等关系的不变式。
读者还可以对比下面的例子:
图2 三角形及其不变式
这个还行,对吧?
那读者再看这个:
图3 错例:等边三角形及其不变式?
这个是不是比较诡异?不过,这样的图倒是符合DDD伪创新的口味:投资少、见效快、门槛低、产量高、仪式感十足。
注意,我在图3中用“==”表示相等关系,而不是用“=”。其实这是违反OCL语法的,OCL里就是“=”表示相等关系,和SQL类似,但考虑到上面说的赋值误解(特别是显示在类图上时),我倒是觉得OCL应该改一下。
那么,可不可以有相等关系的不变式?可以有,但很少。相等关系表达式,经常是出现在前置条件和后置条件,而不是不变式。
什么时候可以有相等关系的不变式,这个就涉及到相当多的知识,不是本文能装得下的了,感兴趣的读者可以关注我的《软件方法》。
三、“订单总价=sum(订单行总价)”的另一个问题
这个问题在《你的医书是假的》中没指出来,在这里补上:
“订单总价=sum(订单行总价)”这个所谓的“不变式”,和图1中的属性名、关联角色名对不上。
图1中的属性名、关联角色名没有“订单总价”和“订单行总价”,只有“订单.总价”、“订单行.总价”——这也说明《DDD诊所》作者当时没有理解不变式是干什么用的。
四、不变式在哪里实现?
上面说了,不变式是一个布尔表达式,它只是说,对象的属性值不能违反这个约束,至于如何保证这一点,它没有做任何指定或暗示。
例如,把每一个不变式封装成一个方法,如果某个操作会修改某不变式中所涉及到属性的值,就调用相应方法来检查——这个工作可不轻松。
如果所用的实现技术支持前置条件、后置条件、不变式等契约编程,例如.NET中提供的Contract类,使用该类提供的服务即可。
五、类似“sum(订单行总价)”的运算会出现在哪里?
可能会有人问这样的问题。
类似“sum(订单行总价)”的运算,像其他针对各个属性的各种运算一样,并没有什么特别,会出现在类的某个操作或多个操作里。
什么操作?正确的回答是“信息不足,不知道”,可能“订单”专门有一个“计算总价”的操作,“sum(订单行总价)”藏在该操作的实现中,也可能“订单”根本不需要有“计算总价”的操作,“sum(订单行总价)”藏在“订单”的某个更复杂的操作的实现中。
不管怎么样,这和图1那个相等关系的“不变式”不存在什么有规律的对应关系。
六、关于付施威的解释
《DDD诊所》作者付施威在《你的医书是假的》的评论区留言解释:
图4 《DDD诊所》作者付施威的解释
先说解释中的第3点:
如果还有“订单总价<3000”这样的约束,之前的结论也没有变化,只不过“订单”的不变式多了一个:
图5 加上订单总价<3000后的类图变化(注:我把类名和属性名改成订单项.价钱)
再说解释中的第1点:
付施威谦虚地解释“DDD诊所是内部活动”、“主要职责是被人研究”,但下面的海报传递出来的信息似乎是不一样的。
图6 活动海报1
图7 活动海报2
开直播以专家身份传道授业解惑没问题,但被指出问题了,又谦虚地说是学习体会,这个似乎就不太好。
七、关于林宁的评论
付施威的同事林宁在《你的医书是假的》下留言:
图8 林宁在《你的医书是假的》评论区的留言
以下的观点并非只针对林宁的评论,而是针对近年DDD圈子的典型反馈——“潘老师说得对,但是%……&¥&**”。
并没有恶语相向,而是潘老师说的没问题,我们也没问题,大家都Happy,这不是挺好吗?
我在《潘老师,你的气度有点小了!》阐述了一些我的看法,本文不再涉及该文中提到的内容。
本文重点展开谈一谈林宁所说的“一定程度的冗余”。
(1)问题①②③
问题①
假设只考虑领域逻辑,不考虑其他问题。我们整理包括需求规约在内的各种各样的素材,(使用面向对象方法)提炼出系统需要封装的各种领域知识,并整理成类模型。模型中,根据不同的变化频率,各种概念分别放置在类、属性、关系等合适的地方,没有冗余。
(可以理解成程序运行在一个存储空间无限大,通信和运算速度无限快且分布在全宇宙的计算机上,不用考虑什么硬盘、内存、Cache、加载,万事俱备,只欠你所分析的领域知识。)
为了方便后面的叙述,我把这称为问题①——这是最难也最想逃避的。
我依然用之前的订单例子,图9左下角的类模型,只涉及目标系统需要封装的领域概念和逻辑,不涉及任何具体实现,我们把它叫作分析模型。
(图9左下角的类模型没有行为部分。如果需要充分表达行为逻辑,可以(使用面向对象方法)建立类的状态机模型,把类的各种行为逻辑分别放在状态机的触发器、迁移动作,状态内动作等合适的地方,同样,没有冗余。)
图9 问题①②③
问题②
现实中的计算机和网络,运行空间、运行速度、通信速度都是有限制的。
如果人们对性能的要求没那么敏感,当前的计算资源又允许,那么实现模型(代码、存储……)和图9左下角的分析模型之间映射非常直接。
假设出现这样的情况:需要频繁地获得订单的总价,而频繁计算订单总价导致出现了不可调和的性能问题,解决方案之一是在实现模型中给“订单”添加一个冗余属性(用数据库语言就是冗余字段)“总价”,这就是《DDD诊所》的情况。图9右上角就是一个C#实现的“订单”类,“总价”前面有个“/”,说明这个属性是派生的(derived)。
为了方便后面的叙述,我把这称为问题②。
*可能有读者会想:这样的话,《DDD诊所》那个“订单总价=sum(订单行总价)”(前文已说过,其实应该是“总价==sum(…订单行.总价.…)”)的不变式不就有了吗?依然没有,领域逻辑并没有变化,分析模型不需要改动。这种添加冗余以及同步的套路不属于领域逻辑,实际上和具体的领域订单、物流、制造、社交……是正交的——这也是常见的批量刷废话套路,把两个正交的东西混在一起。
问题③
假设考虑到开发团队的结构,把系统分成多个“微服务”,分由各个小团队应用各自的技术栈独立完成。这时,可能会在多个“微服务”中有“订单”类。这应该就是林宁说的“拓展系统和团队”。
为了方便后面的叙述,我把这称为问题③,见图9右下角。
*注意:本文列出的问题①②③是对应《DDD诊所》的内容以及林宁的评论内容,不代表只存在这么几个问题。
(2)问题②③的出现对问题①有帮助吗?
没有帮助。
如果问题②③的出现有助于解决问题①,我们早就可以这样干了,不用等到真的有问题②③出现,假想它们存在就行了。
建模人员正在抓耳挠腮地思考和整理各种领域逻辑(问题①),太难了!
有办法。给原问题叠加一个性能问题“10亿并发用户”(问题②),再叠加一个团队问题“100个团队并行开发”(问题③),果然,问题①迎刃而解。
可能会有人提到类似下面这个:
Scott Millett等的“Patterns, Principles, and Practices of Domain-Driven Design”书中举了一个例子,一个庞大的Product类怎样被分解成若干个上下文中的小Product类:
图10 “Patterns, Principles, and Practices of Domain-Driven Design”中的例子
张逸所著的《解构领域驱动设计》中,也用了类似的例子:
图11 《解构领域驱动设计》中的例子
这看起来不就是问题③有助于问题①的解决吗?
其实这是问题①没做好。稍微有建模能力的人,谁会把这么一大堆不同变化频率的知识混到一起?
我写过一篇《发现在写代码过程中对需求的认识更清晰了》谈过类似问题,供参考。
图12 《发现在写代码过程中对需求的认识更清晰了》截图
(3)提防伪创新混水摸鱼
李三正在抓耳挠腮地思考问题①,太难了!
这时候,“创新专家”张四过来推销一种“新方法学”,大意是:环境和时代变了,你需要问题②③。
于是,李三抛开问题①不谈,先搞问题②③,工作量一下就饱满了,看着李三忙忙碌碌,李三的老板也开心。
时间过去,也许问题①没解决,但没关系,问题②③那边没有功劳也有苦劳。
时间过去,也许在忙问题②③的同时,如图12所说,懵懵懂懂,问题①也解决了一些。那就刚好证明张四的“新方法学”有助于解决问题①。
总之,问题②③的引入提供了一层遮羞布,掩盖了李三在问题①上的能力不足问题。
于是,李三觉得张四的新方法学“十分受用”。
(4)可以理解和不能忍
我拓展一下《软件方法》第1章的大楼类比:
两座大楼耸立在那里,要判断地震来了哪座大楼不容易塌,要考虑的是大楼的结构、所用的材料、所在位置的地质环境等,和这座楼是哪家公司建造的,要了多少钱,建造大楼的公司内部是怎样的组织结构,甚至大楼是猫建造的、狗建造的、外星人建造的,没有直接关系。
但要研究这些让楼不容易塌的直接影响因素,涉及到艰深的工程力学、流体力学、岩土力学等知识。架构师李三没把这些知识学扎实,正在那里犯愁呢。
这时,张四出现了。张四说,时代变了,现在盖楼要讲“新建筑学”,要考虑到人际关系,要搞好团结。
于是,李三想着反正“老的”工程力学那些我也搞不懂,还是搞“人”轻松一些。这样吧,有几个包工队跟自己混,就分几个包,大家开干就是。
转换思想后,李三每天累并快乐着,灯红酒绿,推杯换盏。
而且,运气好的时候,盖出来大楼确实也能住人。
**********
如果李三说,公司又不是我的,想那么多干什么,这可以理解;
如果李三说,这么干盖楼快,反正老板要的就是在某某大日子到来之前有个样子货交差,这也可以理解;
如果李三说,这么干有利于建筑团队的安定团结(虽然坑顾客),这也可以理解;
但如果张四、李三组成一个圈子,宣称“新建筑学”盖出来的大楼更抗震,甚至到清华大学建筑学院开课“划时代革命性的工程力学”,取代原有的“工程力学”——这就不能忍了!
(5)最后说一个文风问题
短短一句话,就有“让网变成树”、“切成服务”、“拓展系统和团队”三个可以作为“创新大会”演讲标题的高大上用语。