Architectural Thinking in Functional Languages
My Related Questions box overfloweth with functional programming questions. Having reviewed the most relevant, I'm still curious to hear opinions on the following:
How do you think about structuring an application in a functio开发者_StackOverflow社区nal language?
I'm not talking about a language-specific grammar. I'm interested in conceptual organizational paradigms (e.g object orientation).
Like many, my first exposure to encapsulation and code reuse came from the OO background. As I've been researching different languages, functional programming really caught my eye. I'm beginning to grasp the benefits of immutability, higher-order functions, et cetera. But I still lose my sense of how to structure a functional application without falling back on OO concepts. Actually, many of the functional examples I've seen have more in common with spaghetti code, although I'm sure that's due to the simplicity of the examples rather than any inherent flaw in the functional approach.
This question is kin to "when should I use functional programming," but I've already satisfied myself that the functional approach, despite pros and cons in certain domains, is usable for just about anything that you want. I just have trouble picturing the big-picture organization of a complex app.
In the late 1970s, Barbara Liskov and others developed a boatload of large-scale "object-oriented design" techniques which are still widely used today and which apply unchanged to functional programming. They are easiest to apply with a language that has explicit interfaces and implementations, which means Standard ML (where interfaces are called "signatures" and implementations are called "structures" or "functors") or Objective Caml (where interfaces are called "module types" and implementations are called "modules"). If you prefer Scheme then the "unit" language developed by Matthew Flatt and Matthias Felleisen is built into PLT Scheme and is a very good way of expressing large-scale functions.
In brief:
Organize your applications around abstract types (classes in OO, "abstract types" in FP) and the operations on those types.
Use encapsulation mechanisms (classes in OO, modules in FP) to hide the representations of your abstract types.
Structure your application so that each implementation depends on other implementations indirectly, through their interfaces. This way you limit the amount of code you have to understand to build or modify any one piece of your application.
Go to town!
The main difference is that when you're writing functional programs, you don't use inheritance to reuse implementations. Instead you use higher-order functions, or you use modules which take other modules as parameters.
Summary: at the architectural level, there's not a lot of difference, but when using functional languages you may need to hunt a little harder to find the encapsulation mechanisms that you need.
Most of the overall design patterns are completely applicable:
Separation of Concerns; Model-Control-Presentation (in all of it's variants); Layered Architecture; Input-Process-Output, etc.
Once you've decomposed a big problem into smaller problems, the smaller problems are a matter of working through the various transformations from source to destination representation.
I find that the input-process-output pattern and transformation pipeline patterns help.
精彩评论