吴忠市住房和城乡建设厅网站,营销型网站建设公司提供网站建设,小程序制作用华网天下优惠,宁波哪家做网站好上一篇#xff1a;《把设计模式用起来#xff08;3#xff09;——用不好的原因 之 实践不足》https://blog.csdn.net/nanyu/article/details/141939342 本篇继续讲设计模式用不好的常见原因#xff0c;这是第二个#xff1a;使用设计模式的时机不对。 二、时机不对
这里…上一篇《把设计模式用起来3——用不好的原因 之 实践不足》https://blog.csdn.net/nanyu/article/details/141939342 本篇继续讲设计模式用不好的常见原因这是第二个使用设计模式的时机不对。 二、时机不对
这里说的时机并不是单纯指软件研发周期中的时间阶段而是指条件更具体一点指程序员应该满足什么条件才是使用设计模式的好时机。
第一个条件前面说过了得有问题。第二个条件程序员需具备分析问题的能力。毕竟只有通过分析才能从问题得到模式如图 图 从问题到模式
这张图中最重要的是分析最不重要的是模式。你甚至可以认为一个没学过模式的程序员面对某个具体问题只要分析得当往往也能应用正确的模式只是他自己不知道自己组织代码方式被称作某某模式。
那么我们要如何获得更强的分析能力呢其一对问题所属的业务逻辑越熟悉对问题就越了解其二既然模式是此过程的结果那么熟悉模式也有利于我们强化分析问题的能力。由此我们可以画一张更复杂一点的图 图 问题-分析-模式
尽管熟悉模式倒过来有助于理解问题但程序员的更多努力仍需用在正向路径熟悉业务→理解问题→分析问题→找到并应用正确的设计模式。
在理解问题的基础上思考是否需要以及如何使用设计模式这个结论听起来是如此的自然而然几乎称得上是一条“公理”但确实有很多程序员特别是正在学习设计模式或自诩擅长设计模式的程序员容易违背犯“先有模式然后到处找问题”的错误。
有同学说“老师虽然我心里确实装满设计模式快溢出来的那种但我并不会犯拿模式硬套问题的低级错误相反我总是在看到某个问题和某个模式匹配度很高的情况后才会放心地套用设计模式。”
“只是放心吗难道没有开心”
“当然也开心啊每当用对一次设计模式我的内心充满成就感。”
这正是罪之所在对设计模式的使用有迫切的期待。这是贪欲这是心魔是引发更多软件研发问题的万恶之源。这种心态很容易让我们提倡的“工作逼迫你使用设计模式”变成“你逼迫工作使用设计模式”。 说这么多是在表达一个观点使用设计模式应宁缺勿滥因为一段用错设计模式的代码往往比未使用模式的代码更令后来人头痛。
每一个设计模式都是在表达特定意图Intent的一种组织代码的方式。一段代码用上一个设计模式意味着这段代码至少多出了两个明显的属性一是它的意图二是它的代码结构。一段什么设计模式都没用上代码它就是一段代码而一段代码用上了设计模式代码中的设计模式就像人群有个显眼包它会一直叫嚷“看我看我我的设计意图是……我的实现结构是……”
那么阅读者接收到这两个信息是好事还是坏事这就得看设计模式用对与否。幸福的代码都是相似的不幸的代码却各有各的不幸见表 功能满足 (业务) 模式选择 (意图) 模式实现 (结构) 不幸的效果 ꭗ ꭗ ꭗ 表达了错误的意图且该意图未正确实现程序不对劲 ꭗ ꭗ √ 表达并实现了一个错误的意图程序不对劲 ꭗ √ ꭗ 意图正确但该意图实现有错程序不对劲 √ ꭗ ꭗ 表达了错误的意图且意图实现有误但程序能跑对 √ ꭗ √ 用一个错误的模式实现了程序所需的功能 无论模式选对选错也无论功能满足与否表中几种应用情况中的设计模式都会给代码阅读者带来更多干扰甚至误导毕竟它们会说话。
这里特别讲讲表中最后一类不幸“用一个错误的模式实现了程序所需功能”。这里最常见的“错误”就是用了一个并不需要的模式。比如使用策略模式但直至系统下线也没用上第二个策略。再如实现了一个无比强大的解释器却只用它顺序执行指令。
丁小明严肃地从座位站起来“老师您应知道‘防御性编程’程序员总是预设程序存在问题且将持续需要修改。所以尽管在刚开始做设计时我们无法预测是否有第二个策略但我们应该预设它有。至于解释器的例子确实有点过度设计之嫌但原则上假定未来会有复杂的流程脚本需要执行不对吗”
这是很多同学都会有的疑惑防御性编程是对的可是切忌过度设计也是对的日常编程做设计能不能有一个简单明了且有效的方法能迅速将我们从“加上”和“不要”甚至是“砍掉”的纠结中拉出来
具体到何时使用设计模式这个问题新的疑惑是假设我还没有完全掌握业务需求就被迫写代码那这些代码未来一定会变那么我现在是不是应该预防性地多加使用设计模式毕竟设计模式生来就是为了应对变化。让我们画张图来更清楚的表达 因为会有变化所以就马上用模式 这种想法是错的它把工作理想化了并且弄错了工作首要目标。编程工作首先需保证正确实现当下的功能然后才去考虑如何更好地就应对未来的变化。
为什么是这样先后次序有两个理由第一个略显功利先快点做对再慢慢做好这样比较不会挨训也可以反过来说你上来就花大力气让代码能应对未来的65536种变化大概率也得不到领导夸奖。第二个理由很客观后者依赖前者即通常正是在从不对到不那么对到最终做对的过程中才能对眼下的功能、未来的变化、应有的设计这三者都产生深刻的理解。
丁小明再次发问“有些功能未来会发生的变化在程序员一行代码未写时就可以猜出十之八群这种情况下程序员直接用上设计模式也不合理吗”这种理想状态当然存在。诸如 项目前期工作非常棒需求清晰设计详细详细到此处该用什么模式都写出来了你对此类问题有深刻理解或有可靠的经验此类功能后续的变化路径你看得清楚、也看得长远针对眼前这类问题业界有教科书般的解决方法。
更多的时候程序员处在水深火热中
甲方对现有的功能都说不清楚遑论未来的变化甲方基于防御性心理罗列了各种各样的未来可能的变化甲方没怎么提我方领导、产品经理、程序员自己设想了一大堆甲方没怎么提我方也没怎么想但因为业务领域问题我方并未正确理解甲方的真实需求甲方提了一些我方想了一些并且我方正确地理解了甲方只是不管甲方说还是我方想的都有不对的地方……
如果某一块的功能需求还比较模糊作为乙方千万不要自信可以通过一个“强大的设计”以做到“以不变应万变”从而“立于不败之地”。此时的正确做法应是直接的、快速地把当前所理解的功能做出来并借助它尽快确定相关需求。
对问题的理解是一切设计的基础不过实现设计的过程能极大帮助程序员全面地深入地理解问题。多数时候甲方能告诉你需求但不能帮你做需求分析而程序员因为跨领域的原因所做的需求分析仍然有不少模糊与暧昧。比如功能F1客观上需要的输入是I1、I2、I3但程序员有可能在开始时认为是I1、I3和I4。有很多方法有助发现并纠正这个错误认知其中一种非常高效的方法就是编写代码尝试实现在实现的过程即可验证、强化、纠偏、补充程序员对业务系统的理解包括厘清对象职责和理清对象关系这二者是面向对象和用对设计模式的重要基础。
这是本小节的结论除非你对问题理解到位透彻否则不要一开始写代码就想着使用设计模式在功能写对之前更不要为了该功能“未来可能的变化”去套用设计模式。
这个结论只说了不要那什么时候可以要呢两点
如果你对问题和业务所在领域非常有经验那么可以直接上设计模式以应对未来的变化否则请在变化发生一次、两次、甚至三次的时候再开始考虑使用设计模式重构代码。
台下有同学一脸落莫问“老师我赞同第二点但我们的领导不愿意给我重构所需的资源比如时间怎么办”。这是回到上一小节“实践不足”中的情况B了。你可以屈服从此不去想设计模式的好也可以造反说服领导或想办法让自己当上领导还也可以跳槽。无论如何我都不建议一个程序员在这种恶劣的工作环境下一边要抓紧完成业务功能一边要努力用对设计模式。注意当我说这话时我站边技术主管。本来主管只需检查你功能做对做错现在他需要同时检查功能和模式其中后者还有需区分选择和实现上的错误诸如(a) 功能做错模式选错模式写错(b) 功能做错模式选对模式写错 (c) 功能做对模式选错模式写对……参见表2。
猜技术主管在这种场景下最喜欢说的是哪一句话答“你这是要把错误雕成一朵花吗”
来听一个源于真实案例改编的故事吧。主人公本应是丁小明为节省篇幅我们用“你”来代替。
假设问题为Q正确答案是A而因为理解有误你以为需要实现的业务逻辑是B并且你迅速想到B未来有可能发展成B1、B2、B3。想到这里你一边啜吸奶茶发出嗞嗞嗞的声音一边在脑海中构建原始思路C。为了更好地表达思路也为了更好地应对B1、B2、B3你果断选用设计模式DD的意图是I。不过由于你还是设计模式新人所以你真实想表达的意图其实是J而你写的模式很像D但又不是D称作“D ”。测试一把确实能实现B你充满成就感地提交了代码E。
技术主管开始审查E他迅速嗅到D的味道会心一笑品一口咖啡感觉自己像羽扇纶巾的诸葛亮准备欣赏一场漂亮的战役看看自己的员工如何通过设计模式优雅地干掉Q。10分钟过去20分钟过去30分钟过去……经验老到的主管终于发现D 和 D 只是长得像而已。
主管放下代码翻出上次设计模式内训的文档发现当时你写的答案那叫一个似是而非。他叹一口气陷入自责。
1个小时过去主管猛然领悟你的真实意图是J。
2个小时过去主管醍醐灌顶“这家伙想要实现的业务逻辑是B不是A”不过纵使如此也不应该用D啊看一眼时间是夜里11点30分还早他拨通了你的电话。
夜深人静主管的身边人呼吸均匀偶尔吐一两句梦话。主管轻悄悄地换个姿式继续听话里的你兴奋地谈着“B1、B2、B3变化可能还是保守了我有一种预感三个月以后随着用户量的剧增B99B100B101也是有可能发生的……”
这样的破事来个三四次故事中主人公的工作类型就会发生变化参见上一小节“实践不足”的情况D、情况C、情况A。