首页 > 编程语言 >专业程序员进阶之路:认识设计

专业程序员进阶之路:认识设计

时间:2024-06-17 17:14:34浏览次数:8  
标签:专业 进阶 面向对象 软件设计 接口 程序员 模块 设计 部分

专业程序员进阶之路:认识设计

设计是什么

设计就是构思一套方案,将软件规格说明书的要求转变为可运行的软件的过程。设计将需求和编码连接在一起。

设计有时候可能不是一项明确的活动,但是在项目过程中一直都存在,只是设计进行的程度或深或浅。

大型项目可能有特定的正式设计阶段,由专门的设计人员完成,进行概要设计甚至详细设计。

小型项目可能更多是非正式设计,直接由程序员完成。可能是简单地划分模块、定义接口、描述关系,可能是和别人讨论实现方式,也可能只是在脑海里简单地构思如何实现功能。

为什么需要设计

设计的必要性源自于需求实现的复杂性。当面对简单的需求时,或许不需要复杂的设计。然而,当需求的实现需要跨多个模块或涉及大量代码时,设计就显得尤为重要。

降低复杂度

相较于一项复杂的信息,人类更容易理解多项简单的信息。软件设计的首要目标就是将复杂的问题分解成简单的部分,以便在一个时刻只需要专注于一个特定的部分。当各个部分之间的关系经过精心设计,使得各个部分的相互依赖尽量少,人就更容易在每个时刻都只专注于一部分。

开发协作

软件功能的实现受限于系统架构和人力组织。当一个软件系统的开发人员超过一个时,一个功能往往需要各个部分的负责人进行各种形式的协作才能实现。软件设计的目标就是将功能分解为可以协作的各个部分。通过定义良好的接口,使得各个部分可以独立开发,又可以完整组合。

附加额外价值

考虑一个软件的生命周期,其大部分时间都处于运行维护阶段。将维护工作考虑在内的话,不论是开发者自行维护还是由其他人接手,软件设计的目标又增加了易于调试、理解和扩展。通过增加一些额外的监控措施和运行信息,使得更容易找出故障原因。要让维护人员容易理解,则需要精心设计程序的组织结构,增加程序的可读性。如果软件存在变更和扩展的可能性,那么就需要考虑模块的替换和新增方式。

当开发的部分有可能在其它系统中使用时,可重用性也会是软件设计的目标之一。结合外部需求,增加接口的通用性,梳理出安全的依赖关系,使得功能能够独立存在并且可以不受系统平台的影响。

开发的软件系统具有移植需求时,可移植性也成为了软件设计的目标。精心地将对系统和平台的依赖进行隔离,使得软件系统容易在不同的环境之间进行移植。

设计有哪些挑战

当我们抱着美好的愿望、满怀信心想通过精心的设计来实现我们的想法时,我们会发现设计也会面临大量的挑战。

系统架构和组织约束

设计需要在系统架构下进行,系统架构对设计天然存在种种隐含的限制。当开发工作存在分工时,设计有时也不得不将分工协作的因素考虑在内。

问题的隐含条件

有些问题看似明了实则暗藏玄机,只有在解决问题的过程中或者解决之后才能发现隐藏的约束条件。有时候不得不采取“先实现后设计再实现”的方式来形成一个良好的设计方案。

多条件的平衡取舍

设计同时受到各种条件的限制,设计工作就是要衡量彼此冲突的条件,在各种条件之间做出取舍,尽可能地找到一种平衡。有时候开发时间很重要,有时候响应速度很重要,有时候安全性很重要,不同的追求会形成不同的设计方案。

方案的不确定性

设计不是只有唯一确定的方案,也不存在绝对的正确性。不同的人去设计相同的程序,很可能会得到截然不同的方案,而且每一套方案都很不错。设计的过程就是在探索和试错,不是一个能保证产生预期结果的可重复的过程。设计的结果只要是满足需求的、合理的,应该都是可以被接受的。

什么是好的设计

好的设计常常具有一些普遍性的特征,设计的目标就是让方案尽量多地具备这些特征。当然,正如前面所说,设计的目标之间难免存在一些冲突,而设计的挑战就在于在这些目标之间做出取舍,最终形成一个平衡的方案。

低复杂度

设计的首要目标是降低程序的复杂度,好的设计往往是简单且易于理解的。

可维护性

可维护性意味着程序维护人员能够比较容易地理解整个程序,能够进行修改和扩展,并且清楚改动代码会带来的影响。进行扩展时,不需要破坏系统结构,也不会影响系统的其它部分。

低耦合高内聚

低耦合意味着程序各个部分之间的相互依赖尽可能的少。高内聚意味着系统的特定部分提供的是一组强相关的服务。

可重用性

可重用性意味着当前系统部分可以在其它系统中直接重复使用。

可移植性

可移植性意味着当前系统部分可以很容易移植到其它环境中。

如何进行设计探索

我们很希望有一些明确的指导,告诉我们只要做了哪些步骤,就可以得到一个明确的结果。但对于软件设计来说,这基本行不通,不确定性本来就是软件设计的挑战之一。软件设计是一个探索和试错的过程,使用一些探索性的思考问题的方法,有时能帮助我们产生好的设计结果。

面向对象思考

一说到对象,很多人想到面向对象设计方法和面向对象语言。只有面向对象语言才可以使用面向对象设计方法吗?当然不是。面向对象设计是一种设计思想,而面向对象语言只是这种思想的一种实现工具。其它语言一样可以用来实现面向对象的设计思想。

程序是用来解决现实问题的,所以现实中的对象以及对象之间的相互关系天然地反应在了程序当中。面向对象设计方法就是通过对现实问题的分析,从中识别出对象,定义它的属性和可以提供的功能,确定对象之间的关系和相互可以进行的操作。

识别对象,意味着要给相应的事物一个抽象的概念。抽象让你关注某个概念时可以忽略一些细节,在不同层次处理不同的细节。抽象是降低思考复杂度的有效手段。

定义对象的属性,就是确定它能知道什么,这也决定了它可以提供什么功能。它所能做的和它所知道的要互相匹配。此外,还要明确对象的哪部分是公开的,这部分决定了其它对象如何与它进行交互。通常来说,暴露得越少,会遇到的麻烦也就越少。

识别变与不变

设计面临的重大挑战之一就是要适应变化。要应对这个挑战,必须把易变部分隔离起来,将变化可能带来的影响限制在固定区域。

识别易变部分。好的需求可能提供了一些潜在的变化项目。另外,还有一些多数系统都可能存在的共通性的易变部分:需求不明确的地方,业务规则,硬件,输入输出,设计和编码中的困难部分,等等。

分离易变部分,把识别到的易变部分划分到单独的组件中。

隔离易变部分,设计好易变部分模块的接口,把变化限制在模块的内部,而且不会影响使用者。模块的接口承担了保护内部实现的职责。

特别要注意的是,考虑易变部分时,要区分变化的不同程度和不同原因,进行合理分隔。

保持低耦合高内聚

耦合度表示模块之间联系的紧密程度。好的耦合关系能够使一个模块很容易被其它模块使用。要尽可能让模块保持独立,模块之间的连接也要尽量简单。

模块之间的连接数是耦合度的一个指标。定义越多公共方法的模块与它的调用者的耦合关系显然更紧密。

模块之间的接口是否清晰明了也是衡量耦合度的重要参考。清晰明了的接口让调用者不需要了解模块内部状态和细节。调用一个模块的接口时,如果还需要清楚它的内部实现,是一种可怕的隐藏耦合关系,意味着被调用者的更改很可能影响调用者,哪怕编译没有任何问题。

相互连接的模块能够进行独立演化也是低耦合度的重要特征。保持独立的关键在于对模块附加一层稳定的抽象接口作为契约。只要实现者按契约实现接口,而调用者按契约使用接口,双方就可以独立进行演化。模块的接口参数尽量使用简单类型参数,避免使用复杂对象参数,从而避免参数对象附带的耦合关系。

内聚性指的是模块的代码在支持一个中心目标时的紧密程度。模块包含的一组功能关系越密切,模块的内聚性就越高。当一个模块的功能越集中于一个目标,你就越容易专注于功能本身。

符合设计原则

SOLID (SRP 单一职责原则,OCP 开闭原则,LSP 里氏替换原则,ISP 接口隔离原则,DIP 依赖反转原则)设计原则是一组指导软件设计的基本原则。经过了几十年的发展和演进,实践证明它能有效地帮助我们定义和组织组件和模块,使得这些模块具有可维护性、可扩展性、可复用性和容易理解等特征。

使用设计模式

设计模式提供了很多常见问题的解决方案,而我们遇到的大多数问题都跟这些常见问题相似,因此可以利用类似的模式或方案来解决。

设计模式描述了一些解决常见问题的标准做法,是多年来人们尝试解决那些问题的智慧的积累,其有效性也经过了反复验证。解决类似的问题时,最好使用那些已经存在的经过验证的设计方案,而不是自己再去创造一套。使用常见的设计模式进行设计,其他人也更容易理解方案的设计思路。

丰富的设计模式提供了多种设计方案,设计模式的选择也会启发我们深入去思考,找到问题的本质以及适用的模式。当然,必须避免陷入为了模式而模式的陷阱。

分层

层次结构时人们管理复杂信息的重要手段。常见的分层结构通常将最通用或最抽象的概念放到最高层,而越具体越细节的内容则放到了较低的层次中。

在软件中使用分层结构,让我们只需要专注于当前需要关注的那一层的细节。其它的细节被放到另外的层次上,在需要的时候再去考虑它们。分层提供了比模块更高层次的抽象。

考虑测试需求

将测试需求也加入设计考虑的范畴,要符合单元测试、集成测试和系统测试的要求,软件的各个层级和模块就必须能够进行独立测试,这就要求它们不得不具有松散耦合的特征。

小结

设计是一个富有启发性的过程,需要不断的试验和反思。它不仅是个技术活,更是一种艺术,需要程序员在实践中磨炼,才能真正领悟其深意。只有通过实践,我们才能真正理解设计的力量,将理论知识转化为实用的解决方案,从而在专业程序员的道路上不断进阶。

标签:专业,进阶,面向对象,软件设计,接口,程序员,模块,设计,部分
From: https://www.cnblogs.com/kitsum/p/18252761

相关文章

  • “调包侠”时代已经过去:普通程序员应如何应对新时代的挑战?
    ......
  • 【C++】模板进阶(特化)
      ......
  • SpringBoot配置第三方专业缓存技术Memcached 下载 安装 整合测试 5000字详解
    Memcached下载和安装是一个国内使用量还是比较大的技术打开文件夹我们需要在命令行窗口启动注意要以管理员方式运行先尝试进入指定文件然后又再次运行下载memcached.exe-dinstall启动memcached.exe-dstart停止memcached.exe-dstopmemcached.exe-din......
  • 程序员修炼之道:从小工到专家阅读笔记02
    做程序要及时亡羊补牢修复,这意味着在编程过程中,我们需要时刻关注代码的质量,一旦发现潜在的问题或错误,立即进行修复。遵循编码规范和风格指南,编写易于维护和阅读的代码。这样可以降低出错的可能性,并在出现问题时更容易进行修复。在发现问题时,及时与团队成员沟通,分享自己的发现和解......
  • 程序员修炼之道:从小工到专家阅读笔记01
    程序员要勇于承担错误,这意味着在编程过程中,我们需要敢于面对和解决出现的问题。以下是一些关于勇于承担错误的建议:诚实面对错误:当发现程序中的错误时,不要试图掩盖或忽视它们。诚实地面对问题,承认自己的错误,并寻求解决方案。分析错误原因:在解决问题之前,首先要了解错误发生的原因。......
  • 程序员修炼之道:从小工到专家阅读笔记04
    耦合这个词基本在我的职业生涯中每天都能听到,一个好的程序一定是低耦合的,这本书提出了函数的德墨忒尔法则帮我们更好的界定耦合的边界,怎样编写低耦合的代码,更难能可贵的是这本书不仅仅描述了一般的代码耦合,还花了很大笔墨解释了时间耦合,很多时候一个业务的实现没有必要一定是线性......
  • 程序员修炼之道:从小工到专家阅读笔记03
    这本书的适用范围可以从初学者到有经验的程序员再到项目经理,作为一本偏向理论与思想的书,书中不可避免有些假大空的地方,再加上作者写完本书的时间还在1999年,书中的很多方法与标准放在今天也已不再实用。但这些都不能掩盖它的优秀之处,作者曾在本书完成十年后说过,如果这本书是放在现......
  • 程序员修炼之道:从小工到专家阅读笔记06
    程序需要遵守的实用主义原则。 重复的危害:如果某个事物在代码中重复多次,就可能会在维护过程中带来问题,因为改动了一处而忘记改动另一处造成自相矛盾。这加大了维护难度。要遵守DRY原则,即Don’trepeatyourself。重复通常由这些东西引起:强加的重复,由文档或用户需求决定。这通......
  • 程序员修炼之道:从小工到专家阅读笔记05
    程序员所应该遵循的实用主义原则。 我的源码让猫给吃了:出现错误时,要诚实,不要推诿或者找借口。要提供各种可能的解决方案与后果并与他人沟通,而不是提供借口。 软件的熵:这是著名的破窗户原理。项目中一个小的、无人料理的问题可能带来后续编码时的懈怠,从而造成更大的问题。不......
  • 结合兴趣行业和手头资源来看计算机专业是否还是好的选择,前行路上FlowUs息流一直陪你成
    在这个数字化时代,计算机专业以其广阔的就业前景和持续的行业需求,依旧是许多有志青年的优选。无论你是被编程的逻辑之美所吸引,还是对人工智能的无限可能充满好奇,选择计算机专业意味着你将踏上一条充满挑战与机遇的道路。而FlowUs息流,作为一款强大的知识管理和协同工具,将伴随你......