27

I've tried wedging my clojure diagrams into what's available in UML, using class-blocks as the file-level namespaces and dependency links to show relationships, but it's awkward and tends to discourage functional patterns. I've also tried developing ad-hoc solutions, but I can't discover a solution that works as well as UML with, say, Java (simple directed graphs seem to work in a vague manner, but this the results aren't detailed enough). Furthermore, I'm not finding anything on the web about this.

Just to be clear, I'm not trying to do anything fancy like code generation; I'm just talking about pen-and-paper diagrams mostly for my own benefit. I'm assuming I'm not the first person to have ever considered this for a lisp language.

What solutions have been proposed? Are there any commonly-used standards? What do you recommend? What tools do you use?

albusshin
  • 3,930
  • 3
  • 29
  • 57
jk.
  • 7,572
  • 2
  • 25
  • 22
  • [link]http://stackoverflow.com/questions/2005538/modelling-documenting-functional-programs. And this one, more aimed at haskell/F#/scala: [link]http://stackoverflow.com/questions/2003487/architectural-thinking-in-functional-languages – Gene T Mar 26 '11 at 02:29
  • 1
    JFYI: You can use https://github.com/vbauer/lein-plantuml for modelling. – Vladislav Bauer Aug 19 '14 at 21:29

6 Answers6

13

It depends on what you want to describe in your program.

Dependencies

Use class diagrams to model the dependencies between namespaces; in this case, it's more clear if you use packages instead of classes in a diagram.

You can also use class diagrams to model dependencies between actors

Data flow

You can also use Communication Diagrams to model the flow of data in your program. In this case, depict each namespace as an entity and each function as a method of that entity.

Or, in the case of actors, depict each actor as an entity and each message as a method.

In any case, it's not useful to try and describe the algorithm of your program in UML. In my experience, they are better described in comments in the source file.

Leonel
  • 28,541
  • 26
  • 76
  • 103
9

I think its less about the language and more about your conceptual model. If you are taking a "stream processing" approach then a data-flow network diagram might be the right approach as in some of the Scheme diagrams in SICP. If you are taking a more object oriented approach (which is well supported in Lisp) then UML activity diagrams might make more sense.

Maurice Flanagan
  • 5,179
  • 3
  • 30
  • 37
  • 1
    I really like these examples for low- or mid- level modeling. Here is a similar resource for block diagrams used in control systems modeling: http://en.wikibooks.org/wiki/Control_Systems/Block_Diagrams – jk. Mar 01 '11 at 21:20
  • Great link, and I agree this works best when you are looking at the low / mid level. Sometimes you can fold large amounts of code inside a "block" with relatively simple input / output signals. – Maurice Flanagan Mar 01 '11 at 22:03
8

Well, UML is deeply rooted in OO design (with C++!), so it will be very difficult to map a functional approach with UML. I don't know Clojure that well but you may be able to represent the things that resemble Java classes and interfaces (protocols?), for all the others it will be really hard. FP is more like a series of transformations from input to output, there's no clear UML diagram for that (maybe activity diagrams?). The most common diagrams are for the static structure and the interaction between objects, but they aren't really useful for the FP paradigm. Depending on your goal the component and deployment diagrams can be applicable.

GClaramunt
  • 3,148
  • 1
  • 21
  • 35
8

My personal thought is to model the flow of the data and not the structure of the code because from what i'v seen of large(not really that large) Clojure projects the code layout tends to be really boring, with a huge pile of composeable utilities and one class that threads them together with map, redure, and STM transactions.

Clojure is very flexible in the model you choose and so you may want to go the other way around this. make the diagram first then choose the parts and patterns of the language that cleanly express the model you built.

Arthur Ulfeldt
  • 90,827
  • 27
  • 201
  • 284
5

I don't think something like UML would be a good fit for Clojure - UML is rather focused on the object oriented paradigm which is usually discouraged in Clojure.

When I'm doing functional programming I tend to think much more in terms of data and functions:

  • What data structures do I need? In Clojure this usually boils down to defining a map structure for each important entity I am dealing with. A simple list of fields is often enough in simple cases. In more complex cases with many different entities you will probably want to draw a tree showing the structure of your data (where each node in the tree represents a map or record type)
  • How do these data structures flow through different transformation functions to get the right result? Ideally these are pure functions that take an immutable value as input and produce an immutable value as output. Typically I sketch these as a pipeline / flowchart.

If you've thought through the above well enough, then converting to Clojure code is pretty easy.

  1. Define one or more constructor functions for your data structures, and a write a couple of tests to prove they are working
  2. Write the transformation functions bottom up (i.e. get the most basic operations working and tested first, then compose these together to define the larger functions). Write tests for every function.
  3. If you need utility functions for GUI or IO etc., write them on demand as they are needed.
  4. Glue it all together, testing at the REPL to make sure everything is working.

Note that you source files will typically also be structured in the sequence listed above, with more elementary functions at the top and the higher level composed functions towards the bottom. You shouldn't need any circular dependencies (that's a bad design smell in Clojure). Tests are critical - IMHO much more important in a dynamic language like Clojure than in a statically typed OOP language.

The overall logic of my code is usually the last few lines of my main source code file.

mikera
  • 105,238
  • 25
  • 256
  • 415
2

I have been wrestling with this as well. I find flow charts work great for basic functions and data. It's easy to show the data and data flow that way. Conditionals and recursion are straightforward. UML sequence/collaboration diagrams can capture some of the same info pretty well.

However, once you start using HOF, this does not work well at all.

Normal UML diagrams for packages work ok for namespaces, not that that does much.

Alex Miller
  • 69,183
  • 25
  • 122
  • 167