这是学习笔记的第 2069 篇文章 前几天碰到了一个严重的硬件问题导致服务受到影响,我在总结思考的时候,脑袋里冒出了一个观点:过度设计。 我想了下我们工作中存在很多的过度设计问题,如果细数一下这个过程,可以从功能,性能,可用性这个阶段来说,而归根结底是基于成本,即最小的成本获得最高的收益,这个收益绝非是简单的性能。 ,而过度倾斜就会是上面的这种情况,这种情况下是基于性能的视角来设计的,但是没有充分考虑数据的可用性和可恢复性,所以第三层的设计应该是基于故障的设计方案,我们在设计之初就应该明确服务器是不可靠的,资源是不能完全可靠的 ,我们需要在多个层面进行可用性的设计完善。 常见的过度设计有 1.集群规模过大,但是使用率不高 2.单机多实例设计过度,导致业务难以恢复 3.数据分片过度 ?
如果你严格按照什么瀑布模式、敏捷模式开发的话,你会发现永远是概要设计的评审阶段。 这个时候,屎山还没有成为既定的事实。多位理想主义达人,就会搬出各种规则、规范,来给你的方案下套子。 如果把这种设计哲学推广开来的话,你会发现几乎每个地方都有问题。 项目中使用了Kafka,如果将来换成Pulsar呢?项目中使用了Http,如果将来要换成Socket呢? 但这不代表你可以过度设计。因为用来屏蔽实现的这部分实现,本身就是风险的存在。 耦合有错么? 只要需求落在代码上,就一定会产生耦合,想要去除所有的耦合,那是根本不可能的。
@TOC 新手程序员在做设计时,因为缺乏经验,很容易写出欠设计的代码,但有一些经验的程序员,尤其是在刚学习过设计模式之后,很容易写出过度设计的代码,而这种代码比新手程序员的代码更可怕,过度设计的代码不仅写出来时的成本很高 因为相对于毫无设计的代码,过度设计的代码有比较高的理解成本。说这么多,到底什么是过度设计? 什么是过度设计? 在你解决“拧螺丝”问题的时候,重心早已从解决问题转变为搞一个工具,这就是过度设计。 回到我们原始的需求上来看,如果我们只是需要实现两个整数的加减乘除,这明显过度设计了。 过度设计的坏处 个人总结过度设计有两大坏处,首先就是前期的设计和开发的成本问题。 过度设计也会出现类似的现象,就是缺少通用性,在面对稍有差异的需求上时可能就需要伤筋动骨级别的改造了。 如何避免过度设计 既然过度设计有着成本高和欠灵活的问题,那如何避免过度设计呢!
分享一篇有观点和思考的技术文章 https://www.zhihu.com/question/301150832 一、Algorithm 二、Review 许多文章都在强调不要过度设计自己的系统,但是没有道出个所以然来 ,所以本文列出一些经典的过度设计,希望能给你带来启发,在工程上做一些平衡,避免过度设计把我们推到另外一个复杂度上 1、Engineering is more clever than Business 工程师通常认为自己是最聪明的 即使奇迹般地总结出了一个完美的抽象时,它往往会很快变得不适用,目前最好的代码设计侧重点应该是编码易于被删除的,而不是盲目追求易于扩展 实际上,重复代码比错误的抽象更好,只有当你看到系统里有逻辑重复的代码 HelloWorldPrinter”,那怕事实上只会有特定的数据类型,或者有足够的普通类型签名 发现了策略模式,现在每个条件语句都是一个策略 到处使用枚举/扩展方法/Traits等各种炫酷的技术 上面都体现出了过度适配问题 当设计时,多问自己使用场景是什么,然后深挖下去,你可能会发现大部分特性都是没有必要的,包括可配置性、安全性、可扩展性、可维护性、可继承性。
在实际业务中,你遇到过优化代码却导致过度设计的状况吗? 不管什么等级的技术人,都有一颗想要代码本身结构要好,功能要强大,可阅读性,可理解性,可维护性要到位的初心。 那么也正是这样的初心有时候会导致代码本身过度设计,从而使的简单的代码复杂化。 不过个人在实际业务中,说实话,冗余的代码优化遇到过,过度的代码设计倒是遇到挺少,毕竟整个项目周期都是以功能实现为主,不太会考虑到代码结构的设计。 有哪些方法可以避免代码过度设计呢? 其实,对于代码过度设计的情况,个人遇到的不多,因此可能理解的不是很到位,希望大家谅解。下面谈一下个人的一些看法。 因此来说,代码设计可以在设计之初基于一个基本值去设计,后期根据系统运行情况再逐步迭代完善,这样的话是否可以避免代码过度设计呢。
我相信这一点,因为我们将讨论创建产品时最普遍的问题之一:过度设计产品。依我看,过度设计要比缺乏良好的开发实践扼杀更多的产品。 在讨论详细情况之前,让我来介绍一下我的背景。 如果我们按照维基百科的严格定义来看,过度设计指的是以超过必要的更复杂方式设计产品的事实: 过度设计(或过度工程化,或性能过剩)指的是以过于复杂的方式设计产品或提供问题的解决方案的行为,而在这种情况下,可以证明存在一种更简单的解决方案 嗯,请坐稳椅子,因为在经历了二十年的职业生涯之后,我可以向你保证,过度设计并非例外:这是常态。 过度设计的原因 谁也不是出于恶意这么做的。 一般问题 过度设计的另一个原因往往是缺乏经验。一般而言,你的资历越深,就越不容易过度设计,因为你已经经历过大量的人为复杂性的情况。 如何避免过度设计 在我看来,避免过度设计的最好方法是让你的工程师成为真正的产品工程师。
1 过度设计有意义吗? 看着自己每次根据设计原则及模式的代码重构,虽效果不错,但也自省:如果我的每段代码都这么写,是不是过度设计?把握设计的度,需长久锤炼。 怎么知道系统按照预期工作,就需要有配套自动化测试,最好能TDD,最根本的还是要懂设计,否则,你的代码就是不可测。 代码要说明做什么,而不是怎么做 4 让类和方法的数量最小化 让类和方法的数量最小化,不要过度设计,除非你已看到这必须要做个设计,比如,留下适当扩展点,否则,就不要做。 能做出过度设计的前提,是已懂得各种设计,这时才需要用简单设计的标准对自己约束。所谓简单设计,对大多数人并不“简单”。 没有良好设计,代码就没有可测试的接口,TDD就无从谈起。 不懂设计,重构就只是简单提取方法,改改名字,对代码的改进相当有限。 简单设计的前提是,把编程基础打牢。片面地追求敏捷实践,而忽视基本功,是舍本逐末。
很多人说"过度设计(overdesign)"的时候,说的根本不是设计问题,而是“需求蔓延(requirements creep)”。 比如,搜索引擎搜“过度设计”,第一页出来的这个文章: ? 类似于“架构”、“设计模式”,“过度设计(overdesign)”一词应该也是来源于建筑。 以上文章以为所说问题是“设计”,其实问题是,考虑了不存在的需求,跟设计过度不过度没什么关系。 至于真正的“过度设计”——系统的需求是正确的,但系统内部构造精妙到过分了,呵呵,似乎我见都没见过。 见到的基本上都是伪装成“过度设计”的“没有设计”。 更糟糕的是,“过度设计”还成为拒绝思考的遮羞布——我害怕自己“过度设计”,所以干脆就不学习设计了,这样就避免了陷入“过度设计”的陷阱。
★ 过度设计就像给咖啡杯装上 GPS 追踪系统——看似强大,实则徒增负担。在 .NET 开发中,我们常因追求“完美架构”而陷入设计泥潭。 以下是如何识别并避免这一陷阱的实用指南: ” 过度设计的典型症状 ★ 接口泛滥症: 每个类都强制配套接口 (IUserService, IUserServiceImpl),却仅有一个实现 抽象强迫症 它强调 “只在当前需要时才实现功能,避免过度设计”。 简单来说,就是不要为未来可能用到的功能提前写代码,除非需求已经明确存在。 // 手写日志逻辑... } } // 务实选择: builder.Services.AddSerilog(); // 直接集成成熟日志库 ⚖️ 设计决策平衡表 场景 过度设计方案 务实方案 用务实设计取代过度工程,让每个抽象都经得起“为什么需要它”的灵魂拷问——你的团队和代码库都将因此焕发新生。 (点击关注,修炼不迷路) ▌转载请注明出处,渡人渡己 感谢道友结缘!
在软件开发领域,不陷入过度工程化的陷阱,写出可维护的代码的做法,已经越来越少见了。 领域驱动设计 NO ⛔️ 领域驱动设计是一种软件开发方法,强调对核心业务领域的建模,构建开发人员和利益相关者共享的普遍语言,并根据领域的复杂性设计软件组件。 与DDD类似,实施六边形架构对于具有复杂业务逻辑和众多外部依赖的大型应用程序可能是有益的,但对于中型应用程序来说,这绝对是过度设计。 Design system 设计系统 NO ⛔️ 设计系统是一套可复用的组件、指南和设计原则的集合,用于在多个应用程序或平台上设计一致的用户界面。 总结 过度工程化是所有恶的根源。当涉及到中等规模的应用开发时,我们大多数人都有罪。
过度工程,最初我知道这个词是在 Rod Johnson 的《J2EE Development without EJB》,随着阅历地增长,渐渐发现书中熟悉的场景也在身边再现了。 关于设计模式,我要说什么? 我可以在板书上用 Java 和 C++写出 GoF 23 种设计模式中的每个例子,也学习过 J2EE Core Pattern,可即便这样,又能代表什么? 我的设计能力比起某些牛人来说还是差之许多,我依然在实际的软件开发中的某些情况下,避免使用它们。 是否有过度的架构和过多的框架代码? 架构的价值在于为常见的问题找到好的解决方案,而不是一心想要解决更复杂也更罕见的问题。 在细节上挣扎得越久,就越难以设计出简洁和清晰的方案来。复杂,是软件的唯一天敌。可是简单的设计,又会令人不住地担心,是否会带来不易解决的问题。 这是一个不可调和的矛盾。
Vue 的过渡系统提供了非常多简单的方法设置进入、离开和列表的动效。那么对于数据元素本身的动效呢,比如:
这个系统本来只需要处理两种支付方式,现在却被设计成了可以“轻松扩展”到20种支付方式的架构。 他说:“这样设计扩展性好啊,以后加新支付方式特别方便,代码也显得专业。” 这个瞬间,让我想聊聊这个话题: 在现代后端开发(尤其是微服务时代)中,我们挂在嘴边的那些经典架构模式,90%都是在过度设计。 先澄清一下:我不反对好的设计思想,比如高内聚低耦合、单一职责。我反对的是,把那些为大型单体应用设计的、沉重的、过度抽象的架构模式,生搬硬套到我们现代的微服务、云原生、Serverless的架构里。 过度设计的领域驱动设计(DDD) 经典用法:聚合根、实体、值对象、领域服务、仓储接口、防腐层... 我的吐槽:咱们就是一个用户管理模块,用户有基本信息、地址、权限。 面向变化编程,但不是面向幻想编程:为真实的需求变化做设计,而不是为想象中的“可能”需求做设计。
印度IT巨头印孚瑟斯(Infosys)的创始人纳拉亚纳•穆尔蒂(Narayana Murthy)昨天表示,AI的影响常常被过度夸大了。 他在一次会议上说:“自动化和人工智能只是一种手段。
2)字段冗余 一种典型的反范式设计,利用空间换时间,为了性能而避免join查询。 因此需要单独设计全局主键,以避免跨库主键重复问题。 5 数据迁移、扩容问题 当业务高速发展,面临性能和存储的瓶颈时,才会考虑分片设计,此时就不可避免的需要考虑历史数据迁移的问题。 不到万不得已不用轻易使用分库分表这个大招,避免"过度设计"和"过早优化"。分库分表之前,不要为分而分,先尽力去做力所能及的事情,例如:升级硬件、升级网络、读写分离、索引优化等等。 3 随业务发展需对某些字段垂直拆分 举个例子,假如项目一开始设计的用户表如下: id bigint #用户的ID name
努力付出的边际效应 我们的目标是,在完成重要事项时投入更少,而不是更多,通过约束我们的努力程度而不是通过过度努力来达到目的,这就是轻松行动的意义。 总体讲我认为这本书比较适合处于过度努力区间的人,如果你的的确确付出了很多努力,而没有获得更多回报甚至回报更少了,那么我建议你重新考虑一下自己努力的方向和努力方式。 一般来讲,陷入过度努力陷阱自然也是经历过轻松行动的过程,就是尝过甜头了,但是形成了路径依赖。由于没有及时调整努力策略,就陷入了过度努力的陷阱。
「过度设计」的陷阱:美好愿景,现实打脸⚖️ 如何找到那个黄金平衡点? 我带你一起走进这个复杂的决策过程,从「能用就行」和「过度设计」之间找到一个舒服的角度。 「能用就行」的诱惑:速战速决还是死胡同?谁不想快速交差呢? 「过度设计」的陷阱:美好愿景,现实打脸这该死的完美主义与“能用就行”形成鲜明对比的,便是“过度设计”这一方向。 当你决定为未来的每种需求、每一种变化做出完美设计时,恭喜你,你已踏上了这条“永无止境”的道路。♂️曾经,我也深陷过这种“过度设计”的漩涡。 过度设计看起来有多美好?“过度设计”乍看之下是完美的,因为它可以预见所有可能的变化,似乎一切都被“规划”好了。但现实呢?这些设计真的能在项目开发中发挥作用吗?
过度绘制最直观的影响就是会导致APP卡顿。 Android 过度绘制测试 开启过度绘制检测 点击设置-开发者选项。 点击调试GPU过度绘制 选择调试GPU过度绘制区域 ? 过度绘制展示 原色:无过渡绘制 蓝色:绘制一次 (正常) 绿色:绘制二次 (轻微) 浅红:绘制三次 (中度) 深红:绘制四次 (严重) 一般来说不允许存在4x过度绘制,不允许存在面积超过屏幕1/4浅红或深红色区域 如何优化过度绘制 移除布局中不需要的背景 默认情况下,布局没有背景,这表示布局本身不会直接渲染任何内容。但是,当布局具有背景时,其有可能会导致过度绘制。 移除不必要的背景可以快速提高渲染性能。 使视图层次结构扁平化 借助先进的布局设计方法,您可以轻松对视图进行堆叠和分层,从而打造出精美的设计。 诸如透明动画、淡出和阴影之类的视觉效果都会涉及某种透明度,因此有可能导致严重的过度绘制。您可以通过减少要渲染的透明对象的数量,来改善这些情况下的过度绘制。
setAnimationTransition(_transition:UIView-AnimationTransition, for view:UIView, cache:Bool) //第一个参数: flipFromLeft 从左边滑入 flipFromRight curlUp 从底部 curlDown 从顶部 none //实现翻页的效果 23 func playAnimation() 24 { 25 UIView.beginAnimations(nil, context:ni
过度封装如何毁掉项目 大家在平时开发过程中是否见过在现有spring boot或者asp.netcore官方web开发框架基础上二次创作产生的新框架,例如C#的ABP或者java的javaboot都是基于各自官方基础框架基础上产生的 过度封装 还有一类封装就是过度封装,例如为了应对各类场景,将所有场景代码都进行了封装,产生互相不兼容,为了应对这种不兼容又产生新的代码来绕过不兼容,使原本封装的组件成为了“拦路虎”。