【发布时间】:2011-01-01 14:37:32
【问题描述】:
我发现 UML 可用于记录 OO 系统的各个方面,尤其是用于整体架构的类图和用于说明特定例程的序列图。我想为我的 clojure 应用程序做同样的事情。我目前对模型驱动开发不感兴趣,只是在交流应用程序的工作方式。
UML 是一种通用/合理的函数式编程建模方法吗? FP 中是否有更好的替代 UML 的方法?
【问题讨论】:
标签: functional-programming clojure uml modeling
我发现 UML 可用于记录 OO 系统的各个方面,尤其是用于整体架构的类图和用于说明特定例程的序列图。我想为我的 clojure 应用程序做同样的事情。我目前对模型驱动开发不感兴趣,只是在交流应用程序的工作方式。
UML 是一种通用/合理的函数式编程建模方法吗? FP 中是否有更好的替代 UML 的方法?
【问题讨论】:
标签: functional-programming clojure uml modeling
惯用 Clojure 代码的“单个数据结构上的多个函数”方法淡化了典型的“this uses that”UML 图,因为许多函数最终指向 map/reduce/filter。
我的印象是,由于 Clojure 是一种更以数据为中心的语言,所以当你偷懒时,一种可视化数据流的方式比可视化控制流的方式更有帮助评价考虑。获得构建序列的功能的“管道”图将非常有用。
map 和 reduce 等会将它们变成树
【讨论】:
大多数函数式程序员更喜欢类型而不是图表。 (我的意思是广义上的类型,包括 Caml“模块类型”、SML“签名”和 PLT Scheme“单元”等。)为了传达大型应用程序的工作原理,我建议三件事:
给出每个模块的类型。由于您使用的是 Clojure,您可能想查看 Matthew Flatt 和 Matthias Felleisen 发明的“Units”语言。这个想法是记录模块所依赖和模块提供的类型和操作。
给出接口的导入依赖。这里的图表可能很有用;在许多情况下,您可以使用dot 自动创建图表。这样做的好处是图表总是能准确地反映代码。
对于某些系统,您可能想谈谈实现的重要依赖关系。但通常不会——将接口与实现分开的关键在于,只能根据它们所依赖的接口来理解实现。
最近在architectural thinking in functional languages 上有一个related question。
【讨论】:
这是一个有趣的问题(我已经投了赞成票),我希望你得到的意见至少和你的回答一样多。这是我的贡献:
您想在图表上表示什么?在 OO 中,该问题的一个答案可能是考虑类图、状态(或您喜欢的属性)和方法。所以,显然我会建议,类图不是正确的开始,因为函数没有状态,并且通常实现一个函数(又名方法)。是否有任何其他 UML 图为您的思考提供了更好的起点?答案可能是是的,但您需要考虑要展示的内容并自己找到起点。
一旦你用函数式语言编写了一个(子)系统,那么你就有一个(UML)组件可以在标准类型的图表上表示,但这对你来说可能太高级、太抽象了.
当我编写函数式程序时,我承认这并不多,我倾向于像记录数学函数一样记录函数(我在科学计算领域工作,大量数学运算,所以这对我来说很自然)。对于我编写的每个函数:
一个 ID;
有时是描述;
域的规范;
共域规范;
规则的声明,即函数执行的操作;
有时我也会写后置条件,尽管它们通常由共同域和规则充分指定。
我为此使用 LaTeX,它对数学符号很有用,但任何其他相当灵活的文本或文字处理器都可以。至于图表,没有那么多。但这可能反映了我在功能上编程的系统设计的原始状态。我的大部分计算都是在浮点数数组上完成的,所以我的大部分函数都非常容易编写ad-hoc,并且系统的结构非常松散。我想象一个图表,它将函数显示为节点,将输入/输出显示为节点之间的边——在我的情况下,在大多数情况下,每对节点之间都会有边。我不确定绘制这样的图表是否会对我有所帮助。
我似乎倾向于告诉您不,UML 不是对功能系统进行建模的合理方法。是否常见 SO 会告诉我们。
【讨论】:
这也是我一直在尝试尝试的东西,在使用 Ruby 编程几年后,我已经习惯了类/对象建模。最后,我认为我为 Clojure 库创建的设计类型实际上与我为大型 C 程序所做的非常相似。
首先勾勒出领域模型的轮廓。列出围绕对这些数据执行的主要功能移动的主要数据。我把这些写在我的笔记本上,很多时候它只是一个名字,下面有 3-5 个要点。这个大纲可能会很好地近似您的初始命名空间,并且应该指出一些关键的高级接口。
如果看起来很简单,那么我将为高级接口创建空函数,然后开始填充它们。通常每个高级函数都需要几个支持函数,并且在构建整个接口时会找到分享更多代码的机会,因此您可以随时进行重构。
如果这似乎是一个更困难的问题,那么我将开始绘制数据结构和关键功能流程的图表。通常,最有意义的图表和概念模型将取决于您选择在特定设计中使用的抽象类型。例如,如果您为 Swing GUI 使用数据流库,那么使用依赖图将是有意义的,但如果您正在编写服务器来处理关系数据库查询,那么您可能想要绘制代理池和用于处理元组的管道。我认为这些类型的模型和图表在向其他开发人员传达程序的架构方面也更具描述性。它们显示了系统各方面之间更多的功能连接,而不是像 UML 这样的东西所传达的非常非特定的信息。
【讨论】: