Search code examples
functionumlclass-diagram

How do I represent the type of an argument in a UML class diagram, when the argument is a function?


For example, a class has a method compute() (using Python syntax and dropping the self argument for clarity):

def compute(computation_fn):
    return computation_fn(5)

Let's assume that computation_fn maps int to int. In a UML class diagram, should I write something like this?

+ compute(computation_fn: (num: int): int): int

If this has already been answered somewhere, just drop a link! I've been trying to look for an answer.


Solution

  • UML does only have the basic types Integer, Boolean, String, UnlimitedNatural, and Real.

    You can also use any class that you define in your model as type. In this regard, you can very well define a class that corresponds to a kind of functions, for example FunctionOfIntToInt. That's usual business in any design that uses callables.

    UML may also be enriched with additional types in a profile. Very often, you'll see types of your favourite language used. This assumes the use of a language specific profile. But usually it's fixed type names (e.g. Date, UInt8, ...). You could imagine a type called as (int):int, but this would be ambiguous in regard of UML's syntax that uses already :.

    Unfortunately, there's nothing in UML's typing system that would allow to represent functions with arbitrary number of arguments of flexible type. So it all depends how compliant you need to be with UML:

    • Python programmers would understand any python type that you'd use in the diagram, including function types, even if it's not "pure" UML. So this would be pragmatic approach. I'll recommend nevertheless to replace the : for the return type with -> to avoid lexical confusion
    • But if you have to go by the book, profiles don't allow for a syntax extension that would allow to compose types on the top of existing UML mechanisms. There's a workaround. You could use an UML template class to represent functions. The first argument would be the return type, and the remaining template arguments the argument types. You'd then use UML's native template binding syntax to instantiate the template for typing purpose. But I agree, it's more clumsy (even if it'd seem familiar to any user of C++ std::function template.