设计模式学习笔记 - 设计模式与范式 -总结:2.实际开发中如何避免过度设计,如何避免设计不足?

概述

设计模式的理论部分已经学完了。我想你一定蠢蠢欲动,想要赶紧实践一下,把这些理论知识应用到自己的项目中。不过,要注意下面两点:

  • 一种是过度设计。在开始编写代码之前,花很长的时间做代码设计,在开发过程中应用各种设计模式,希望代码更加灵活,为未来的扩展打好基础。这其实是过度设计,未来的需求并不一定会实现,变相地增加了代码的复杂度。
  • 还有一种是设计不足。怎么简单怎么来,写出来的代码能跑就可以,顶多算式 demo,看似在实践 KISS、YAGNI 原则,实则忽略了设计环节,代码毫无扩展性、灵活性可言,添加、修改一个很小的功能就要改动很多代码。

所以,本章和你聊聊,在实际的项目开发中,如何避免过度设计,以及如何避免设计不足。


设计的初衷是提高代码质量

应用设计模式只是方法,最终的目的是 “初心”,是提高代码的质量。具体点说,提高代码的可读性、可扩展性、可维护性等。所有的设计都是围绕着这个初心来做的。

所以,在做代码设计的时候,你一定要先问下自己,为什么要这样设计,为什么要应用这种设计模式,这样做是否能真正地提高代码质量,能提高代码质量的哪些方面。如果自己很难讲清楚,或者给出的理由比较牵强,没有压倒性优势,那基本上就可以断定这是一种过度设计,是为了设计而设计。

实际上**,设计原则和思想是心法,设计模式只是招式**。掌握心法,以不变应万变,无招胜有招。所以,设计原则和设计思想更加普适、重要。掌握了设计原则和思想,我们能更加清楚的了解为什么要用这种设计模式,就能恰到好处的应用设计模式,甚至我们还可以自己创造出来新的设计模式。

设计的过程是先有问题后有方案

如果我们把写出的代码看作作品,那做产品时,我们先要思考痛点在哪里,用户的真正需求在哪里,然后再看要开发哪些功能去满足,而不是先拍脑袋相处一个花哨的功能,再去东搬西凑编出一个需求来。

代码设计也是类似。我们要先去分析代码存在的痛点,比如可读性不好、可扩展性不好等等,然后再针对性地利用设计模式去改善而不是看到某个应用场景后,觉得跟之前在某本书中看到的某个设计模式的应用场景很相似,就套用上去,也不考虑是否合适,最后如果有人问起了,就再找几个不痛不痒、很不具体的伪需求来搪塞,比如提高了代码的可扩展性、满足了开闭原则。

实际上,很多没有太多开发经验的新手,往往在学完设计模式之后会非常 “学生气”,那原理当真理,不懂得具体问题具体分析,手里拿着锤子看哪都是钉子,不分青红皂白,上来就是套用某个设计模式。写完之后,看着自己写的很复杂的代码,还沾沾自喜,甚至到处炫耀。这完全是无知地炫技,半瓶子不满大抵就是这样子的。等你慢慢成长之后,回过头来在看自己当年写的代码,我相信你应该会感到脸红。这里主要是告诉你,要防止过度设计

所以,在之前的文章中,一直都是从问题讲起,一步一步的给你剖析为什么要用设计模式,而不是一开始就告诉你最终的设计。实际上,最重要的是想培养你分析问题、解决问题的能力。这样,看到某段代码之后,你就能自己分析得头头是道,说出它好的地方、不好的地方,为什么好、为什么不好,不好的如何改善,可以应用哪种设计模式,应该之后有哪些副作用要控制等等。

相反,如果你只是掌握了理论知识,即便是把 23 种设计模式的原理和实现都背的滚瓜烂熟,不具备具体问题具体分析的能力,在面对真实项目的千变万化的代码时,很容易就会滥用设计模式,过度设计

设计的应用场景是复杂代码

很多设计模式的教程都会举一些简单的例子,这些例子仅仅只有教学意义,只是为了奖设计模式的原理和实现,力求在有限的篇幅内给你讲明白。而很多人误以为这些简单的例子就是这些设计模式的经典应用场景,常常照葫芦画瓢地应用到自己的项目中,用复杂的设计模式去解决简单的问题,还振振有词地说某某书中就是这么写的。这是很多初学者因为缺乏经验,在学完设计模式之后,在项目中过度设计的首要原因。

前面我们讲到,设计模式要干的事情就是解耦,也就是利用更好的代码结构将一大堆代码拆分成职责更单一的小类,让其满足高内聚低耦合等特性。

  • 创建型模式是将创建和使用解耦
  • 结构型模式是将不同的功能代码解耦
  • 行为型模式是将不同的行为代码解耦

而解耦的主要模式是应对代码的复杂性,设计模式就是为了解决复杂代码问题而产生的。

因此,对于复杂代码,比如项目代码量多、开发周期长、参与开发人员多,我们前期要多花时间在设计上,越是复杂代码,花在设计上的时间就要越多

不仅如此,每次提交的代码,都要保证代码质量,都要经过足够的思考和精心的设计,这样才能避免烂代码效应(每次提交的代码质量都不是太好,最终积累起来整个项目的质量就变得很差)。

相反,如果你参与的只是一个简单的项目,代码量不多,开发人员也不多,那简单的问题用简单的解决方案就好,不要引入过于负责的设计模式,将简单问题复杂化

持续重构能有效避免过度设计

我们知道,应用设计模式会提高代码的可扩展性,但同时也会带来代码的可读性的降低,复杂度的升高。一旦我们引入某个复杂的设计,之后即便在很长一段时间都没有扩展的需求,我们也不可能将这个复杂的设计删除,整个团队都要一直背负着这个复杂的设计前行。

为了避免错误的需求预判导致的过度设计,我非常推崇持续重构的开发方法。持续重构不仅仅是保证代码质量的重要手段,也是避免过度设计的有效方法。在真正有痛点的时候,我们再去考虑用设计模式来解决,而不是一开始就为不一定实现的未来需求而应用设计模式。

当对要不要应用某种设计模式感到模棱两可的时候,你可以思考下,如果暂时不用这种设计模式,随着代码的演进,当某一天不得不去使用它时,重构的代码是否很大。如果不是,那能不用就不用,怎么简单怎么来。说句实话,对于 10 万行以内的代码,团队成员稳定,对代码涉及的业务比较熟悉的情况下,即便所有的代码都推到重写,也不会花太多的时间,因此也不必为代码的扩展性太多担忧。

避免设计不足的 3 个必要条件

前面讲的都是如何避免过度设计,下面再稍微讲讲如何避免设计不足。

首先,你要有一定的理论知识储备

比如你熟练掌握各种设计原则、思想、编码规范、设计模式。理论知识是解决问题的工具,时前任只会的结晶。没有理论知识,就相当于游戏中没有厉害的装备,虽然可以靠身手徒手打怪,但肯定会影响你最高水平的发挥。

其次,你还要有一定的刻意训练

很多同学很苦恼,说理论知识都学过,但是很容易忘记,遇到问题也想不到对应的知识点。实际上,就是缺乏理论结合实际的刻意训练。没有经过刻意训练,知识积累不了,能力也锻炼不了,等于白学。

最后,你一定要有代码质量意识、设计意识

在写代码之前,要多想想未来会有哪些扩展的需求,哪部分是会变的,哪部分是不会变的,这样写会不会导致之后添加新的功能比较困难,代码的可读性好不好等代码质量问题。有了这样的意识,你就里写出高质量的代码不远了。

不脱离具体场景去谈设计

设计是一个非常主观的事情,不夸张地讲,可以称之为一门 “艺术”。相应的,好坏就很难评判了。如果真的要评判,我们就要放到具体的场景中。脱离具体的场景去谈论设计是否合理,都是空谈。

比如,一个手游项目能否被市场接收,往往非常不确定。很多手游项目开发出来之后,市场反馈很差,立马就放弃了。此外,尽快上市占领市场也是一款手游致胜的关键。所以,对于手游项目的开发来说,往往前期不会花太多的时间在代码设计、代码质量上。

相反,如果你开发的是大型端游,一般都要投资上亿资金,几百号人开发好几年,推倒重来的成本很大。这个时候,代码质量就非常关键了。前期就要多花点时间在设计上,否则,代码质量太差,bug 太多,后期无法维护,也会导致很多用户弃用而选择同类型的其他家的游戏。

再比如,开发的是偏底层、框架类、通用的代码,那代码质量就比较重要,因为一旦出现问题或者代码改动,影响面就比较大。相反,如果我们开发的是业务系统或者不需要长期维护的项目,那稍微放低点代码质量的要求,也是没有问题的,而且,自己的代码跟其他项目没有太多耦合,即便出了问题,影响也不大。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/824260.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

聊聊linux的文件缓存

序 本文主要研究一下linux的文件缓存 文件缓存 linux使用page cache来缓存最近读取的文件,也有目录结构(dcache: Directory Entry Cache)缓存及inode缓存,它们都使用了LRU算法来管理这些page及dentries cache vmstat ## vmstat procs -----------me…

智享ai自动直播系统,直播界的流量增长点。

智享ai自动直播系统,直播界的流量增长点! 在当今互联网时代,商家面临着日益激烈的竞争,因为一切内容如价格都变得透明,商家们纷纷寻求新的增长点来获取流量。在线下资源饱和的情况下,线上短视频平台成为商…

Acrobat Pro DC2024安装包(亲测可用)

目录 一、软件简介 二、软件下载 一、软件简介 Acrobat软件是由Adobe公司开发的一款专业的PDF(Portable Document Format,便携式文档格式)编辑和管理软件。它为用户提供了丰富的功能,涵盖了创建、编辑、转换和共享PDF文件、签名和…

从选品策划、变现、数据分析、App矩阵多方面,分享App蓝海精细化运营玩法

本篇分享主要分为以下两部分: 通过七麦和蝉大师等数据工具或者同行网站选出蓝海产品; 通过版本、语言、皮肤等实现 App 矩阵,获得更多用户并进行差异化变现。 文章目录 —前言—选品标准一个小案例更进阶的选品思路流量变现App 矩阵最后总结—前言— 据官方统计,App St…

使用嘉立创EDA打开JSON格式的PCB及原理图

一、将PCB和原理图放同一文件夹 并打包成.zip文件 二、打开嘉立创EDA并导入.zip文件 文件 -> 导入 -> 嘉立创EDA标准版/专业版 三、选择.zip文件并选择 “导入文件并提取库” 四、自定义工程路径 完成导入并转换为.eprj文件 五、视频教学 bilibili_使用立创EDA打开JSO…

工业自动化,3D视觉技术3C薄片自动化上料

随着制造业的快速发展,3C行业对薄片类零件的上料需求日益增长。传统的上料方式往往依赖于人工操作,效率低下且存在误差。为了解决这一问题,3D视觉技术应运而生,为3C薄片自动化上料提供了强大的技术支持。本文将探讨3D视觉技术如何…

go语言net包里面的PostForm

net包里面的http包里定义了Request结构体,用于http的请求, type Request type Request struct { // Method指定HTTP方法(GET、POST、PUT等)。对客户端,““代表GET。 Method string // URL在服务端表示被请求的URI&…

论文阅读-Federated-Unlearning-With-Momentum-Degradation

论文阅读-Federated Unlearning With Momentum Degradation 联邦忘却与动量退化 Yian Zhao IEEE Internet of Things Journal 2023 年 10 月 2 日 CCF-C momentum degradation-MoDe 动量退化 memory guidance-记忆引导 knowledge erasure-知识擦除 Deep-learning neural n…

Docker 更新容器状态 开启/关闭 开机自启动

开启(开机 自启动 容器) docker update --restartalways {容器ID/Name}关闭(开机 自启动 容器) docker update --restartno {容器ID/Name}我们下期见,拜拜!

C++如何使用string类

文章目录 为什么要学习string?库中的string关于编码ASCII编码Unicode编码 迭代器Iteratorsstring常用构造接口接口声明与功能说明接口演示 string类对象的容量操作接口声明与功能说明接口演示reverse与resize在不同平台下的扩容与缩容机制 string类对象的访问及遍历操作接口声…

CUDA 以及MPI并行矩阵乘连接服务器运算vscode配置

一、CUDA Vscode配置 (一)扩展安装 本地安装 服务器端安装 (二) CUDA 配置 .vscode c_cpp_properties.json {"configurations": [{"name": "Linux","includePath": ["${workspa…

【iOS】—— SDWebImage源码学习(2)(源码解读)

【iOS】—— SDWebImage源码学习(2)(源码解读) 1.UIKit层取消当前正在进行的异步下载占位图策略判断url是否合法下载图片操作 2. SDWebImageManager判断url是否合法判断已加载失败的url保存操作查找缓存 3. SDWebImageDownloaderS…

ReactNative实现 RSC Render 的解决方案

方案探索 在 React Native 中可以使用零 Bundle 大小的 React 服务器组件吗? 由于需要适应快速的产品模块发布请求,要求在App不发版的场景下,对首页的Banner进行动态更新。 当下RN所支持的热更新已经可以满足大部分需求,但是也…

【C++类和对象】拷贝构造与赋值运算符重载

💞💞 前言 hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥个人主页&#x…

ES6的编程风格

ES6 提出了两个新的声明变量的命令:let和const。其中,let完全可以取代var,因为两者语义相同,而且let没有副作用。 var命令存在变量提升效用,let命令没有这个问题 if (true) {console.log(x); // ReferenceErrorlet x…

分布式搭载博客网站

一.运行环境: IP主机名系统服务192.168.118.128Server-WebLinuxWeb192.168.118.131Server-NFS-DNSLinuxNFS/DNS 二.基础配置 1. 配置主机名,hosts映射 [rootserver ~]# hostnamectl set-hostname Server-Web [rootserver ~]# hostname Server-Web [r…

【学习笔记】Python大数据处理与分析——数据预处理

一、数据清洗 1、唯一值与重复值 获取唯一值的方法是采用unique()函数,用于Series对象: s1 pd.Series([2, 3, 4, 1, 2, 5, 3, 6, 4, 9, 5, 3, 4, 2, 1, 2])print(s1.unique()) →[2 3 4 1 5 6 9] 但unique()函数不能用于DataFrame对象,而d…

DNS是TCP还是UDP

既使用TCP也使用UDP 1. 域名解析时用UDP 在大多数情况下,DNS请求使用UDP协议,因为UDP协议可以提供较高的效率和安全性,尤其是在查询的响应大小较小(通常不超过512字节)时。非可靠连接,因为传输的数据量小…

Word分节后,页码不连续、转PDF每节后多出空白页解决办法

1. 问题图例 废话少说,先上图: 2. 问题分析 问题分析:出现以上问题的原因可能有, 未链接到上一节页面布局中节的起始位置设置为[奇数页] 3. 解决问题 若为【1. 未链接到上一节】导致该问题出现,则我们需要选中页脚…

【QT教程】QML Web多媒体处理

QML Web多媒体处理 使用AI技术辅助生成 QT界面美化视频课程 QT性能优化视频课程 QT原理与源码分析视频课程 QT QML C扩展开发视频课程 免费QT视频课程 您可以看免费1000个QT技术视频 免费QT视频课程 QT统计图和QT数据可视化视频免费看 免费QT视频课程 QT性能优化视频免费看 免…