关于系统设计的一些思考
0.前言
当我们站在系统设计的起点,面对一个新的需求,我们该如何开始呢?这是许多处于系统分析与设计领域的新手常常思考的问题。有些人可能会误以为,只要掌握了诸如面向对象
、统一建模语言
、设计模式
、微服务
、Serverless
、ServiceMesh
、DDD
这样的标准方法论或新潮或深奥的理论,就能顺利地进行设计了。然而,经过实践我们会发现很多系统设计都是要对具体情况进行详细的权衡分析。我要说,虽然这些工具、方法、技能很重要,但它们绝不是成为优秀设计师的充分或是必要条件。无数的实践告诉我,没有捷径可走,唯有在实践中不断地学习、总结、反思,我们才能真正地成长。
在这个过程中,我们会发现,系统设计更多的是一种选择和妥协
。其实小到一件事情,大到人生抉择,无外乎都是在选择和妥协中寻找一种平衡点。做系统设计也一样。所以了解架构评估的同学肯定会想到架构评估中的一种j经典评估方法,ATAM(架构权衡评估方法)
.。此处不做赘述。
有的观点可能是基于作者的经历整理,可能存在局限性,大家可以求同存异。不喜可以略过后面的了
1. 妥协:寻找平衡点
那么我们如何做到妥协,寻找到合适的平衡点呢
系统设计的目标众多,包括但不仅限于功能、性能、健壮性、开发周期、交付日期等。这些目标往往很多时候是矛盾的
。不要一上来就说你的服务如何划分,你的健壮性如何稳定,你打算做的技术选型多么先进,不要认为自身已经学了很多主流的架构设计和各种技术架构,就能搞成很优秀的系统,永远不要追求所谓的什么优秀,除非单纯的是为了KPI。因为优秀只是可以讲出来的炫耀。而真正合适才是系统设计最终要表达的。
例如,你可能会发现,提高软件性能往往会导致开发周期的延长、交付日期的推迟;盲目地增加功能可能会导致性能降低、维护成本增加。这时,我们需要在这些众多的目标中找到一个平衡点,明确知道如何设计能实现这个平衡。这个平衡点应该是公司或客户都能接受的。在可行性分析阶段,我们通常会论述这样一个平衡点。但是,如果我们发现没有这样一个平衡点,那么我们可能需要重新思考需求,提出放弃某个方面的过度要求,否则系统将很可能失败。
甚至我们如果做项目,我们评估的工时为300人天,根据目前的资源评估,需要2个月交付。但是客户要求1个月内交付。这种情况下,我们如何做系统设计。通常一般供应商标准的如下
- 减少功能复杂度
- 风险评估
- 寻求外包或合作
- 调整开发计划项目组加班工作
.通常还有一种策略叫做客户教育
。其实就是向客户解释为什么项目需要300人天的工作量,并且你需要列举出很多权衡点。让他们理解项目复杂性和所需工作量之间的关系,以及为什么压缩进度可能会影响交付结果,把权衡点的妥协达成变成和客户一起完成的,这样客户的期待和项目本身的预期在前期就有了共识。
2. 学习
了解和选择解决方案
系统设计是一个复杂的过程,需要深厚的专业知识和丰富的实践经验。需要了解各种可以解决问题的方案,并清楚知道各个方案的效果、成本、缺点,以及这些方案的区别,然后从中作出最佳选择。这不是一个人能在一两天内完成的,需要长时间的学习和实践。
3. 借鉴
站在巨人的肩膀上
我们常常需要参考其他与目标系统相类似的系统,对其中的内容进行筛选、取舍和补充,以此作为新系统的设计。这并不是因为我们缺乏创新,而是因为我们需要站在巨人的肩膀上,借鉴前人的经验和智慧,避免重复犯错误。
4. 规律
系统设计的几个要点
尽管系统设计的过程中充满了困扰和挑战,但是也并非没有规律可循。我发现,优秀的系统设计通常在以下几个方面表现出色:
- 组件的独立性。审视自己设计的系统,是否做到了高内聚、低耦合?
- 例外的识别和处理。我们不能期待用户会完全按照说明书操作,系统应该能够正确处理各种例外情况。
- 防错和容错。当网络中断、数据库崩溃这样的灾难性事件发生时,我们的系统也能稳定运行吗?
此外,我也发现了一些技术和方法能够有效改进系统设计,包括降低复杂性、通过合约进行设计、原型化设计、错误树分析等。
总的来说,系统设计是一项挑战和机遇并存的工作。我希望,通过分享我的一些想法和经验,能够帮助到正在走在这条路上的你。让我们一起在实践中学习,一起在挑战中成长,成为优秀的系统设计师。
从需求到表示的艺术
软件设计是一门结合技术与艺术的学问,它要求我们将抽象的软件需求转化为具体的软件表示形式。这个过程像是在绘制一幅蓝图,我们最初描绘出软件的总体框架,然后逐步细化,直至在这个框架中填满每一个细节。通过这样的艺术创作,我们才能实现功能强大、性能优异、用户友好的软件产品。让我们来共同探讨软件设计的两个阶段以及一些主要的设计方法。
软件设计的两个阶段
从工程管理的角度来说,我观察到软件设计过程中可以明显区分出两个阶段:
-
概要设计:也被称为高层设计。在这一阶段,设计师的任务是将软件需求转化为数据结构和软件的系统结构。如果我们采用的是结构化设计方法,那么我们会从一个宏观的角度将软件划分成各个组成模块,并且确定这些模块的职责以及模块之间的调用关系。这一步骤的完成标志着软件设计的框架已经搭建完成。
-
详细设计:亦称为低层设计。这一阶段,我们对概要设计中的结构表示进行更进一步的细化,这包括定义详细的数据结构以及算法的实现方式。在此基础上,如果还是采用结构化设计,那么详细设计的任务就是为每一个模块具体化设计,确保整个系统的每个部分都有明确和可执行的设计方案。
主要的设计方法比较
在结构化设计方法盛行的年代,设计师们有多种设计技术可以选择。其中包括Jackson方法和Parnas方法。结构化设计方法强调模块的独立性和功能的单一性,致力于使模块间的联系尽量弱化而模块内部的联系紧密。而Jackson方法的独到之处在于,它从数据结构出发,导出相应的模块结构。Parnas方法则把重点放在抽象的概念上,其核心思想是封装变化,将容易变化的因素隐藏在模块内部,这样当这些因素发生变化时,对系统的影响可以被局限在最小范围。Parnas方法给出了一些重要的设计准则,虽然它没有提供具体的工作步骤,但它的影响仍然深远。
而在近年来,随着对象技术的崛起,这一方法凭借其对数据的高效封装能力和良好的消息机制,实现了高内聚、低耦合的系统设计,逐渐成为现代软件设计的主流方法学。对象技术不仅促进了软件模块化,而且还提高了代码的重用性,使得软件开发更加高效、系统更加稳定。
在软件设计的世界里,无论是传统的结构化方法还是现代的对象技术,都有其独特的价值和适用场景。作为设计师,我们需要根据项目的具体需求、团队的技术背景以及项目的预算情况来选择最合适的设计方法,以确保软件设计的成功。最终,无论我们采取哪种方法,软件设计的本质始终是将用户的需求转化为一个可以工作的软件系统,这是一个既需要科学性也需要创造性的挑战过程。
相关文章:

关于系统设计的一些思考
0.前言 当我们站在系统设计的起点,面对一个新的需求,我们该如何开始呢?这是许多处于系统分析与设计领域的新手常常思考的问题。有些人可能会误以为,只要掌握了诸如面向对象、统一建模语言、设计模式、微服务、Serverless、Servic…...

Java 第19章 IO流 课堂练习+本章作业
文章目录 Buffered流拷贝二进制文件创建文件写入文本读取文本文件存读Properties文件 Buffered流拷贝二进制文件 package com.hspedu.chapter19.outputStream;import java.io.*;public class BufferedCopy02 {public static void main(String[] args) {String srcFilePath &q…...

一键制作电子样册,提升企业品牌形象
电子样册作为一种新型的宣传方式,具有许多优势。首先,它打破了传统纸质宣传册的局限性,可以随时随地展示企业的产品和服务。其次,电子样册可以通过多媒体形式展示企业的品牌形象,包括图片、视频、文字等多种形式&…...

Linux 的引导与服务控制
一 开机启动过程 bios加电自检-->mbr-->grub-->加载内核文件-->启动进程 1 bios家电自检 检测硬件是否正常,然后根据bios中的启动项设置,去找内核文件 2 mbr 因为grup太大,第一个扇区存不下所有的grub程序,所以分为2部分指…...

多输入多输出 | MATLAB实现SSA-CNN麻雀算法优化卷积神经网络多输入多输出预测
多输入多输出 | MATLAB实现SSA-CNN麻雀算法优化卷积神经网络多输入多输出预测 目录 多输入多输出 | MATLAB实现SSA-CNN麻雀算法优化卷积神经网络多输入多输出预测预测效果基本介绍模型背景程序设计参考资料 预测效果 基本介绍 MATLAB实现SSA-CNN麻雀算法优化卷积神经网络多输入…...

高端电流检测方案
随着过去传统的“开环”系统被智能和高效率“闭环”设计所取代,准确的电流检测在多种应用中变得越来越重要。常见的电流检测方法,需要将检流电阻串联进被测电流通路,再用放大电路放大检流电阻上的压降。这个放大电路常被称之为电流检测放大器…...

IP地址、子网掩码与网络地址
一、IP地址 在 TCP/IP 体系中,IP 地址是一个最基本的概念。IP地址的作用:实现和网上的其他设备进行通信 IP地址的表示方法 互联网上的每台主机(或路由器)的每个接口都分配一个全世界唯一的IP地址。该IP地址由ICANN分配。 IP地址…...

python 深度学习 记录遇到的报错问题10
本篇继python 深度学习 解决遇到的报错问题9_module d2l.torch has no attribute train_ch3-CSDN博客 一、CUDA error: no kernel image is available for execution on the device CUDA kernel errors might be asynchronously reported at some other API call,so the stackt…...

linux下docker搭建Prometheus +SNMP Exporter +Grafana进行核心路由器交换机监控
一、安装 Docker 和 Docker Compose https://docs.docker.com/get-docker/ # 安装 Docker sudo apt-get update sudo apt-get install -y docker.io# 安装 Docker Compose sudo apt-get install -y docker-compose二、创建配置文件及测试平台是否正常 1、选个文件夹作为自建…...

Github 2023-12-31 开源项目日报 Top10
根据Github Trendings的统计,今日(2023-12-31统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量TypeScript项目3Swift项目1Java项目1HTML项目1Astro项目1Python项目1C项目1Dart项目1Jupyter Notebook项目1C项…...

管程-第三十三天
目录 为什么要引入管程 管程的定义和基本特征 用管程解决生产者消费者问题 结论 本节思维导图 为什么要引入管程 原因:在解决进程的同步与互斥问题时,信号量机制存在编写困难和易出错的问题 能不能设计一种机制,让程序员写程序时不再需…...

嵌入式中断理解
一、概念 中断: 在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行。 中断优先级&#x…...
React16源码: Hooks源码实现
Hooks 1 )概述 Hooks 在 React16.7版本出现的新功能Hooks 改变了整体应用开发的模式,同时开发体验会和以前会变得不一样Hooks 让函数组件具有类组件的能力 在 function component 里面没有this无法保存 state通过 Hooks可以让 function component 代替…...

华为端口隔离高级用法经典案例
最终效果: pc4不能ping通pc5,pc5能ping通pc4 pc1不能和pc2、pc3通,但pc2和pc3能互通 vlan batch 2 interface Vlanif1 ip address 10.0.0.254 255.255.255.0 interface Vlanif2 ip address 192.168.2.1 255.255.255.0 interface MEth0/0/1 i…...
java项目启动jar包启动参数设置端口号
默认启动 java -jar myapp.jar 指定配置文件 java -jar myapp.jar --spring.profiles.activedev 指定端口号 java -jar myapp.jar --server.port8080 后台启动 nohup java -jar myapp.jar --server.port8080 >outlog.log 2>&1 &...

【数据结构和算法】寻找数组的中心下标
其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 前缀和的解题模板 2.1.1 最长递增子序列长度 2.1.2 寻找数组中第 k 大的元素 2.1.3 最长公共子序列…...

多粒度在研究中的应用
FontDiffuser: One-Shot Font Generation via Denoising Diffusion with Multi-Scale Content Aggregation and Style Contrastive Learning 存在的问题 现有的字体生成方法虽然取得了令人满意的性能,但在处理复杂字和风格变化较大的字符(尤其是中文字符)时&#x…...
Docker命令---查看容器日志
介绍 使用docker命令查看容器输出的日志 示例 docker logs 容器ID...

Spring Boot 基于Redisson实现注解式分布式锁
依赖版本 JDK 17 Spring Boot 3.2.0 Redisson 3.25.0 源码地址:Gitee 导入依赖 <properties><redisson.version>3.25.0</redisson.version> </properties><dependencies><dependency><groupId>org.projectlombok</…...
Javascript 正则表达式零宽断言
在介绍正则表达式零宽断言这个概念之前,先看一下以下这道有关 javascript 正则表达式的题目: 登录注册流程是前端最常见的业务流程之一,注册流程少不了密码强弱度校验,请实现对密码的校验,要求满足: 包含大…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...

Java中HashMap底层原理深度解析:从数据结构到红黑树优化
一、HashMap概述与核心特性 HashMap作为Java集合框架中最常用的数据结构之一,是基于哈希表的Map接口非同步实现。它允许使用null键和null值(但只能有一个null键),并且不保证映射顺序的恒久不变。与Hashtable相比,Hash…...

vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能
vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能 查看官网:https://vxetable.cn 效果 代码 通过 checkbox-config.isShift 启用批量选中,启用后按住快捷键和鼠标批量选取 <template><div><vxe-grid v-bind"gri…...