软件系统架构设计的目标不在于设计本身,而在于架构设计意图的传达。图形化有助于在团队间进行高效的信息同步,但不同的图形化方式需要语义一致性和效率间实现平衡。C4模型通过不同的抽象层级来表达系统的静态结构,并提供了最小集的抽象建模元素,为设计人员提供了一种低认知负载、易于学习和使用的高效建模方式。
软件系统架构设计的目标不在于设计本身,而在于架构设计意图的传达。如果不能清晰、一致的在干系人间进行设计意图的同步,即使再好的设计也只是空中楼阁。软件架构设计本质上也是一种抽象和建模的过程(对模型和抽象的本质参考文章《 领域驱动设计开篇 》),软件架构设计模型的表达有多种方式:图形化、语言和文字。绝大部分场景下,图形化在架构设计的表现力层面效果更佳。因此,对于软件系统架构进行可视化表达是有价值,且是必要的。
软件架构可视化的方式有多种,不同的团队有不同的实践方式,最为常见的由如下几种:
不同的可视化方式各有优劣,以下部分将对不同的表现形式进行说明
线框图是最为通用的可视化表达方式之一,架构师或设计人员大量的架构图,比如技术架构、功能架构、数据架构、逻辑架构等等都通过线框图的形式表达。该种可视化方式的优势是:
但,基于线框图表达软件系统架构存在的问题也非常明显:语义的一致性问题
你可能自己画过很多软件系统架构图,也可能参与评审过其他团队的架构图,我相信,对你而言并不是的所有的图都是“清晰且易于理解的”。举个简单的场景,如果我们在百度搜索 “架构图” ,你可能得到以下结果:

各式各样的 “架构图”:不同形状和颜色的图形元素、不同形状和颜色的连线、不同的意图。
我们可以看出:线框图虽然简单,但其其图形化的语义一致性是大问题。虽然都是通过线框表达软件系统架构,但不同的人可能使用不同的元素、不同的颜色、不同的连线和分层等等,线框自由表达的灵活性和图形化语义的一致性存在潜在冲突,最终都会阻碍架构设计意图传达。
UML是统一建模语言,相比于线框图而言,其优势是在软件建模层面提供了一致性的建模元语言。简单来说,UML提供了大家达成一致的(UML支持扩展的场景除外)建模元素。如果团队成员比较熟悉UML,那么通过UML表达的系统架构图天然具有认知一致性。
丰富灵活的建模元语言在提升语义一致性的同时,也必然会导致复杂性的上升。掌握UML具有一定的学习成本,而熟练的应用对研发人员也提出了更高的要求。基于 Simon Brown给出的数据,实际情况只有少数团队真正使用UML。不论是UML的复杂度和学习成本原因,还是敏捷化下对UML的排斥,很多团队都放弃了UML。
我们不能否认UML的价值,基于统一建模语言能够更有效的进行架构设计的信息传递和沟通,也能基于UML提供的详细的模型图元素进行充分的设计表达。团队中是否要基于UML进行沟通需要权衡,虽然UML不能表达你所要传达的全部的架构信息,但其在某些维度的表达相对比较适合。
架构可视化另一个非常常见的方式是:草图。草图是一种非正式的、易于快速沟通的图形化方式。团队基于特定的场景,可以通过草图的形式进行快速的沟通,以便高效的在干系人间拉齐关键信息。
但,草图的劣势与线框图一样:语义一致性低
我们可以在白板上 “随心所欲” 的画各式各样的草图,草图上的元素、连线,又或者布局都可能是涌现式的、临时性的,这些草图的价值在于 “会话周期内的高效沟通”。如果干系人没有完全参与到草图的讨论,又或是后置查看,大概也很难精准捕获这些草图所要表达的设计意图。

团队需要统一语言进行高效沟通 !!!
C4模型在不同的级别提供了统一的抽象以表达软件系统的静态结构。如下图所示:

我们要构建的系统不会孤立存在,都会依赖现有的IT设施。要明确我们构建的系统是什么,宏观上需要回答:我们的系统如何融入到现有的IT设施。
系统上下文图正是从高层视角表述待构建系统与当前IT设施的交互及边界。通过上下文图:

更进一步的剖析核心系统,回答:系统由哪些容器组成?容器的职责是什么?以及相关的高层的技术选型是什么?
与Docker的容器概念不同,C4模型的容器是在 “系统” 作用域之下,其表达的是组成系统的可独立可部署的物理单元。以下图为例:单个容器元素重包含了名称、职责描述、技术选型,同时,容器间的连线及标注标识了其高层的交互协议及交互形式。

进一步的剖析容器,回答:容器由哪些组件组成?这些组件的职责及组件间的交互形式是什么?
具体到每个容器内部,通过多个组件及组件间的关系表达容器的组成。“组件” 本身是一个泛化的概念,C4模型的组件是在 “容器” 的作用域之下,其表现形式可能是独立的Jar包,或者是应用内独立的包,也可能是类级别,但逻辑上都能够表达一个组件的概念。对于组件图关键的是要表示清楚组件的实现选型、组件职责以及组件间的交互关系。

代码处于C4模型的最低层,且是可选的,其关注的是实现相关。C4模型并没有对实现层面的可视化进行统一抽象,开发人员可以选择UML类图、E-R图等进行可视化。是否需要提现代码层面研发人员基于具体情况具体分析,一般情况下,如果系统中需要重点关注的部分可以考虑一些代码级别的图支持,比如,我们非常关注系统设计的可扩展性,则关键部分可能需要一些类图表达;又或者非常关注底层数据模型,则E-R图可以纳入考虑范围。

连线表达依赖关系还是数据流向 ?
都可以,C4模型中的连线既可以表达依赖方向,也可以表达数据流向。原则上,设计人员需要保证其清晰且无歧义。实践中一般通过合理的文字说明来明确的表达元素间的关系。
Jar或类库应该建模为“容器”? “组件” ?
Jar包或类库一般是链接到调用方的进程中,作为进程中的一部分存在,这种依赖一般不表示为容器,而是组件。当然,是否要将Jar,比如SDK表示为组件并体现在组件图上需要设计人员具体情况具体分析。
数据存储系统应该建模为 “软件系统” 还是 “容器” ?
数据存储系统,比如MySQL、DFS等一般是作为独立的外部存储集群存在,集群的运维可能归属于公司的运维团队。以OSS为例,但从应用角度而言,即使集群的运维不归属当前开发团队,团队也会申请租户隔离的专属空间,因此,在C4模型中这种情况应该表述为 “容器”。
消息系统应该如何建模 ?
消息系统一般作为两个容器间的交互媒介,因此在C4模型中消息系统的建模存在两种方式:
图形化的过期问题
C4模型本身也是一种文档化机制,同样也存在过期问题。只不过C4模型通过对系统在不同的层级进行抽象,每个抽象层级的过期频率不同,由上到下逐渐增大,上下文图的变化频率最小,而代码级则变化最大。
为什么C4不涉及业务流、状态机、数据模型等建模
C4模型仅对系统的静态结构进行建模,并不试图囊括或替代其它建模方式,C4模型并不适合所有维度的可视化表达。对于业务流可以基于BPML、UML活动图进行表达,状态机可以基于UML状态机图进行表达,而数据模型可以通过E-R图表达,不同建模语言相互补充。
作为架构师或系统设计人员,在进行系统架构设计时一般会关注不同维度,一般情况下,对于业务系统建设而言,会关注以下维度。在架构设计(架构和设计)过程中,基于C4模型、UML及BPML等多种建模方式相互补充,不同表现维度下可以采用不同的建模方式
软件架构设计的终极目标不在于设计本身,而在于架构设计意图的传达。图形化有助于在团队间进行高效的信息同步,但不同的图形化方式在语义一致性和效率间存在平衡。C4模型通过不同的抽象层级来表达系统的静态结构,并提供了最小及的抽象建模元素,为设计人员提供了一种低认知负载、易于学习和使用的高效的建模方式。在实际项目落地过程中,结合C4模型以及UML、线框图等组合方式对架构设计进行可视化表达,一定程度上能够提升团队对架构设计认知的一致性以及建模效率。
作者:倪新明
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
我即将开始一个将录制和编辑音频文件的项目,我正在寻找一个好的库(最好是Ruby,但会考虑Java或.NET以外的任何库)以进行实时可视化波形。有人知道我应该从哪里开始搜索吗? 最佳答案 要流入浏览器的数据量很大。Flash或Flex图表可能是唯一能提高内存效率的解决方案。Javascript图表往往会因大型数据集而崩溃。 关于ruby-Ruby中的波形可视化,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.c
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub
我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
@作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors 1、什么是behaviors 2、behaviors的工作方式 3、创建behavior 4、导入并使用behavior 5、behavior中所有可用的节点 6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors 1、什么是behaviorsbehaviors是小程序中,用于实现
了解Rails缓存如何工作的人可以真正帮助我。这是嵌套在Rails::Initializer.runblock中的代码:config.after_initializedoSomeClass.const_set'SOME_CONST','SOME_VAL'end现在,如果我运行script/server并发出请求,一切都很好。然而,在我的Rails应用程序的第二个请求中,一切都因单元化常量错误而变得糟糕。在生产模式下,我可以成功发出第二个请求,这意味着常量仍然存在。我已通过将以上内容更改为以下内容来解决问题:config.after_initializedorequire'some_cl