views:

216

answers:

4

I've found UML useful for documenting various aspects of OO systems, particularly class diagrams for overall architecture and sequence diagrams to illustrate particular routines. I'd like to do the same kind of thing for my clojure applications. I'm not currently interested in Model Driven Development, simply on communicating how applications work.

Is UML a common / reasonable approach to modelling functional programming? Is there a better alternative to UML for FP?

+3  A: 

Hi

It's an interesting question (I've upvoted it), I expect you'll get at least as many opinions as you do responses. Here's my contribution:

What do you want to represent on your diagrams ? In OO one answer to that question might be, considering class diagrams, state (or attributes if you prefer) and methods. So, obviously I would suggest, class diagrams are not the right thing to start from since functions have no state and, generally, implement one function (aka method). Do any of the other UML diagrams provide a better starting point for your thinking ? The answer is probably yes but you need to consider what you want to show and find that starting point yourself.

Once you've written a (sub-)system in a functional language, then you have a (UML) component to represent on the standard sorts of diagram, but perhaps that is too high-level, too abstract, for you.

When I write functional programs, which is not a lot I admit, I tend to document functions as I would document mathematical functions (I work in scientific computing, lots of maths knocking around so this is quite natural for me). For each function I write:

-- an ID;

-- sometimes, a description;

-- a specification of the domain;

-- a specification of the co-domain;

-- a statement of the rule, ie the operation that the function performs;

-- sometimes I write post-conditions too though these are usually adequately specified by the co-domain and rule.

I use LaTeX for this, it's good for mathematical notation, but any other reasonably flexible text or word processor would do. As for diagrams, no not so much. But that's probably a reflection of the primitive state of the design of the systems I program functionally. Most of my computing is done on arrays of floating-point numbers, so most of my functions are very easy to compose ad-hoc and the structuring of a system is very loose. I imagine a diagram which showed functions as nodes and inputs/outputs as edges between nodes -- in my case there would be edges between each pair of nodes in most cases. I'm not sure drawing such a diagram would help me at all.

I seem to be coming down on the side of telling you no, UML is not a reasonable way of modelling functional systems. Whether it's common SO will tell us.

Regards

Mark

High Performance Mark
There are two things I particularly want to communicate beside function description (also important, but supported well in-language, usually). The first is an overview of an application as a set of modules, in order to quickly communicate what the application can do, and how the functionality is divided between modules. The second is to show how functions fit together in one particular operation (e.g. responding to a specific web request or end-user command line call). I'm still something of an FP newbie though, so it's possible I'm asking for the wrong things.
Jim Downing
But it seems that you are beginning to answer your own question .. you've indicated the need for 2 types of diagram, overview and module. What are your preferred UML diagram types to start adapting for your FP requirements ?
High Performance Mark
For the overview I'd start with a class diag, but a component diag seems like a better fit. For the flows a sequence diag would probably be reasonable, with parameters flowing right and return values flowing left. How to represent a returned function and its evaluation, though?
Jim Downing
+3  A: 

the "many functions on a single data structure" approach of idiomatic Clojure code waters down the typical "this uses that" UML diagram because many of the functions end up pointing at map/reduce/filter.
I get the impression that because Clojure is a somewhat more data centric language a way of visualizing the flow of data could help more than a way of visualizing control flow when you take lazy evaluation into account. It would be really useful to get a "pipe line" diagram of the functions that build sequences.
map and reduce etc would turn these into trees

Arthur Ulfeldt
+3  A: 
Norman Ramsey
+1  A: 

This is something I've been trying to experiment with also, and after a few years of programming in Ruby I was used to class/object modeling. In the end I think the types of designs I create for Clojure libraries are actually pretty similar to what I would do for a large C program.

Start by doing an outline of the domain model. List the main pieces of data being moved around the primary functions being performed on this data. I write these in my notebook and a lot of the time it will be just a name with 3-5 bullet points underneath it. This outline will probably be a good approximation of your initial namespaces, and it should point out some of the key high level interfaces.

If it seems pretty straight forward then I'll create empty functions for the high level interface, and just start filling them in. Typically each high level function will require a couple support functions, and as you build up the whole interface you will find opportunities for sharing more code, so you refactor as you go.

If it seems like a more difficult problem then I'll start diagramming out the structure of the data and the flow of key functions. Often times the diagram and conceptual model that makes the most sense will depend on the type of abstractions you choose to use in a specific design. For example if you use a dataflow library for a Swing GUI then using a dependency graph would make sense, but if you are writing a server to processing relational database queries then you might want to diagram pools of agents and pipelines for processing tuples. I think these kinds of models and diagrams are also much more descriptive in terms of conveying to another developer how a program is architected. They show more of the functional connectivity between aspects of your system, rather than the pretty non-specific information conveyed by something like UML.