I've added a new module to JPrinciple recently to enable the developer to constrain access to third party libraries to designated parts of the code. The reason for this is that I sometimes see processing json in app layer or using the Mongo API from the domain in our codebase. Being an ardent DDD proponent, I just cannot have that happening again! So the idea is that you can specify which libraries you allow access to in which layer. All the layers around the specified one can use those libraries of course, but nothing under it. Hope it made some sense. Probably it's better to see through an example
The new part is the <thirdparty>...</thirdparty>. It says that anything under org.apache.commons can be referenced in the Domain layer and up (app and infrastrucure), and the Infrastructure layer can use anything under the listed package paths: org.apache.maven,org.json,org.yaml,com.google.common.collect,jdepend. Anything else used in Infrastructure, e.g. something under org.mongo, would cause an alert. So would the reference to org.json in Domain, since it's only allowed in Infrastructure.
The visual idea behind it is that your code is a castle with multiple circles of defending walls around it. You let foreign troops leaking into your territory only until certain walls. Different troops can have different privileges, one (org.yaml) can only set up his tent inside the outmost wall (Infrastructure), the other (org.apache.commons) is allowed to enter the inner sanctum (Domain). Usable from version 0.25.
Friday, 15 August 2014
Wednesday, 13 August 2014
Clojure, syntax and readability
def isValidVoter(p:Person) = p.age > 18 && !p.isInPrison
vs
(defn is-valid-voter [p] (and (> (:age p) 18) (not (:in-prison p))))
The first expression is in Scala, the second in Clojure. As much as I appreciate the simpleness of Clojure-syntax, I can't help but find the Scala version much easier to read. The Clojure version can be enhanced by line breaks
(defn is-valid-voter [p]
(and
(> (:age p) 18)
(not (:in-prison p))))
but now it's a four-liner instead of a one-liner. And yet still less readable than its Scala counterpart. Furthermore, if I want to remove the "in-prison" part, in Scala I just remove the end of the expression from the && sign without touching anything from the left of it.
def isValidVoter(p:Person) = p.age > 18 && !p.isInPrison
Back to the question of readability, part of it is due to our learnt preference for infix notation. But the real reason is, I think, is that the different parts of the function definition, such as name, arguments, body, just don't stand out in Lisp. Check this
(defn wrap [x] [x])
It lacks arbitrary rules like "there is a '=' between the expression signature and the body", "prefix a boolean expression with an '!' negates it" or "get the field of an object with <object>.<field>", and so on. Taking uniformity to its extreme, undeniably some readability is lost. But what is gained is not only the esthetic statisfaction over the ultimate simplicity, but the power coming from homoiconity, macros. Macros are discussed elsewhere, but I'm as much as fascinated by the simplicity itself as by the power it brings. There are many syntaxes with different advantages and disadvantages. Languages are evolving and we can't know how a programming language will look like in a hundred years. But Lisp is on a very end of the spectrum. It cannot get any simpler.
Friday, 8 August 2014
OO, invariants and Clojure
In an object-oriented language if we'd like to implement a "concept", we create a class. Concept is too abstract (and probably there are better words out there for what I tried to say), so let's see a practical example. I want to implement a game of cards and therefore I'd like to deal with "decks". My OO-language of choice is Scala. Assuming that the operations I want to do on a deck are pulling a card from top, shuffle, and adding cards on the top, the code would look like this: (ignore Scala's awkward way of simulating enumerations - why is that so bad in this otherwise beautifully concise language is beyond me).
I chose to implement the deck as an immutable objects, all functions on it creating a new instance and leaving the original intact. I could have done the more OO-way of mutable state, but it's irrelevant for the case and I'd like to move the solution close to the one of Clojure discussed later.
See the check in the "constructor" and the isValidDeck function. This ensures that our Deck is always "valid". All the code using this class can safely assume that it doesn't contain duplicate cards. It's the simplest invariant I could come up, but serves the purpose of the post well. If I try to get out of my default OO-mindset acquired in the last 10 years and look at it with fresh eyes, what I see that we have a "raw" data structure, a list, and certain constraints attached to it. The data structure and the constraints together are the class.
The state-space of the Deck object obviously couldn't be bigger than that of the list, the raw data. So building a class around a raw data structure is simply imposing restrictions on how the underlying data can be modified by the clients of the class. Of course the methods of a class can hide side-effects, too, but again, in the aspect of invariants, it's not relevant.
The benefit of the OO approach is that the Deck stands guard over its invariants, so the constrains and the data "travel together". The disadvantage is that we lose all the already existing data-manipulating functions the language would provide out of the box. Let's demonstrate it with the Clojure solution.
Delightfully simple. We didn't have to write any of the required functions, the language gives us them all and plenty more. What if we want to remove all the Clubs from the Deck? Or halve it? Or order by some specific rule? Clojure would offer a million different data manipulation choices. So would Scala anyway if you choose to use it that way, but the language philosophy prefers encapsulating data and behaviour in one unit (class).
The disadvantage of Clojure's lightweight way is that we now lost the guard on the invariants. You can pass an arbitrary list to any functions expecting a valid deck, opening the door for hard to detect bugs. However I think there is a remedy for this and quite an easy one of that.
Using the 'with-invariant' function we can apply any validation with any function operating on any data structure. We can extend it easily to deal with multiple inputs, too, or different validations for the input and the output. Object-oriented programming ties validation and data together, offering very strong safeguards, but constraining reusability immensely.
Imagine now we want to extend our game of cards program by allowing different kind of games, including ones where the deck can contain duplicates. Or requires different operations on the deck (like pull from the bottom). Can we reuse the Deck class? Not in this current form. Maybe subclassing it or extract some traits? Either way the code starts to get complicated.
With Clojure we just use the same basic data structure (list) a new validator function with with-invariant or build it up in one single function for brevity's sake. The Clojure implementation dissected the class and cleaved off the constraints from the data. The data structure can processed in almost every imaginable way with the rich set of functions built-in the language, and the constraints can be plugged-in the computation whenever needed.
I chose to implement the deck as an immutable objects, all functions on it creating a new instance and leaving the original intact. I could have done the more OO-way of mutable state, but it's irrelevant for the case and I'd like to move the solution close to the one of Clojure discussed later.
See the check in the "constructor" and the isValidDeck function. This ensures that our Deck is always "valid". All the code using this class can safely assume that it doesn't contain duplicate cards. It's the simplest invariant I could come up, but serves the purpose of the post well. If I try to get out of my default OO-mindset acquired in the last 10 years and look at it with fresh eyes, what I see that we have a "raw" data structure, a list, and certain constraints attached to it. The data structure and the constraints together are the class.
Class = raw data structure + constraints
The state-space of the Deck object obviously couldn't be bigger than that of the list, the raw data. So building a class around a raw data structure is simply imposing restrictions on how the underlying data can be modified by the clients of the class. Of course the methods of a class can hide side-effects, too, but again, in the aspect of invariants, it's not relevant.
The benefit of the OO approach is that the Deck stands guard over its invariants, so the constrains and the data "travel together". The disadvantage is that we lose all the already existing data-manipulating functions the language would provide out of the box. Let's demonstrate it with the Clojure solution.
Delightfully simple. We didn't have to write any of the required functions, the language gives us them all and plenty more. What if we want to remove all the Clubs from the Deck? Or halve it? Or order by some specific rule? Clojure would offer a million different data manipulation choices. So would Scala anyway if you choose to use it that way, but the language philosophy prefers encapsulating data and behaviour in one unit (class).
The disadvantage of Clojure's lightweight way is that we now lost the guard on the invariants. You can pass an arbitrary list to any functions expecting a valid deck, opening the door for hard to detect bugs. However I think there is a remedy for this and quite an easy one of that.
Using the 'with-invariant' function we can apply any validation with any function operating on any data structure. We can extend it easily to deal with multiple inputs, too, or different validations for the input and the output. Object-oriented programming ties validation and data together, offering very strong safeguards, but constraining reusability immensely.
Classes vs (raw data + validator functions) = safety vs reusability
Imagine now we want to extend our game of cards program by allowing different kind of games, including ones where the deck can contain duplicates. Or requires different operations on the deck (like pull from the bottom). Can we reuse the Deck class? Not in this current form. Maybe subclassing it or extract some traits? Either way the code starts to get complicated.
With Clojure we just use the same basic data structure (list) a new validator function with with-invariant or build it up in one single function for brevity's sake. The Clojure implementation dissected the class and cleaved off the constraints from the data. The data structure can processed in almost every imaginable way with the rich set of functions built-in the language, and the constraints can be plugged-in the computation whenever needed.
Thursday, 17 July 2014
Implementing a DDD project in Clojure - 2
One important thing I forgot to mention (even realize) in the first post is the applicability of the Dependency Inversion Principle for Clojure. In a DDD application adhering to Hexagonal Architecture the Domain layer is at the bottom of the dependency-chain. It has interfaces (Secondary Ports) implemented (as Secondary Adapters) in the Infrastructure layer, so the direction of dependency is the inverse of the direction of control-flow. In Clojure you can achieve the same with Protocols, but without application context and objects we need a Namespace (I called it registry) to instantiate the implementations and the Namespaces that use the Protocol have to depend on it. So through the registry the high-level Namespaces depend on the low-level ones. I don't know yet how to resolve it, if it's doable at all.
Friday, 11 July 2014
Clojure - " java.lang.Exception: Cyclic load dependency"
I've just discovered that Clojure, by default, doesn't allow cyclic dependencies between namespaces, as opposed to Java, where those between classes are allowed. Cyclic dependencies being the root of many evils, that is a very good thing. It would be nice to find the same strictness imposed on package levels, but it's not.
Labels:
Clojure
Implementing a DDD project in Clojure - 1
In the last couple of weeks I've been occupying myself with porting the Blackjack Java project to Clojure. I've been curious whether DDD concepts could be reused in a functional language without sacrificing idiomaticity. There is still a long way to go, but the walking (limping) skeleton is ready. Check it on github. In the followings I make an attempt to summarize my experiences.
1. Aggregates
First of all Clojure strongly encourages working with immutable data structures. My naive assumption had been that an OO aggregate can be simply substituted with a data structure accompanied by a handful of functions operating on it. This is only partially true. Though I've found state mutation easily replaceable with creating a new data structure (Clojure's persistent data structures make it performant, and its very effective data manipulation functions easy) as the output of the applied function, but I'm not convinced about how invariants should be preserved in the absence of an entity with mutable state. To some degree it can be achieved by :pre and :post constraints on the individual functions, but I haven't really dived into it.
2. Domain events
Related to the previous point, since in OO aggregate roots are to publish domain events. Initially I implemented my "aggregates" the same way, the functions operating on them published events as a side-effect. But eventually I've realized it's very non-FP, so instead of invoking a side-effect, I changed these functions to return not only the updated data structure (the new state of the "aggregate"), but the event-list as well. Then the new "state" is updated in the DB and the events are sent out. This solution (which could be applied in OO as well) eliminates the need of thread-local/event store-flushing magic I resorted to in the java version. I am more than satisfied with this, it's not only idiomatic, but makes things so much simpler.
3. AOP for locking
This is quite pleasing also. Instead of aspects and annotations, it's a 5-(short)-line macro.
4. Layering
The most interesting part. In the very few books mentioning the large-scale structure of FP-programs I've stumbled across the notion of onion-layering, not unlike that of DDD or Hexagonal Architecture. We should strive to confine the mutable states to the outer layers, keeping the core completely functional. Unfortunately in OO-DDD, the "core" is the Domain, which does have logic with side-effects. Repository interfaces and Domain Services as front-doors to ACLs are very much part of the Domain, and are there to enable the Domain to interact with the external world (writing to DB, sending messages, calling web services, ...).
So quite early it became clear that the layering in FP-programs requires some changes in the OO-way of thinking.
4.1 Hexagonal Architecture
If we forget about DDD temporarily and reach back to HA (which I think is one of the foundations of the former), some parallels with the FP-version of onion-layering are obvious. In HA, the Adapters are outside of the core and the Ports are the joints that bind the Adapters to the core. Even an FP-program must interact with the external world (otherwise what's the point of writing it), so HA, with its explicitly designated areas of external interaction seems to be a natural fit.
4.2 Application layer
Having a clean facade for an application has nothing to do with OO or FP, so keeping this layer of DDD seemed ok. In addition to the normal DDD application layer responsibilities, such as locks, transactions and orchestration, I decided all calls to secondary (driving) ports should happen here (calls to a remote Bounded Context, Blackjack Wallet, interacting with the DB). This is the external layer of the onion (still beneath the adapters-layer, though).
I've kept different namespaces in this layer for the different modules (Player, Table, Game) and used most method names for commands with bangs.
4.3 Core (Domain) layer
A purely functional layer. I've tried to simply port the java version's Domain here, minus the secondary (driving ports), e.g. the Game-, Player-, TableRepository or the WalletService, which I've decided to put under a port package on the same level as app and domain. Secondary ports neither defined (but in their own package) or used (but in app services, see previous point) here.
4.4. Infrastructure layer
Quite the same as in the java version. Adapters are implemented as Records of Protocols, see next point.
5. Using Protocols for secondary ports
I've tried to avoid OO-techniques as much as possible, but protocols simply seem to be the right way to implement ports.
6. Application Context and Dependency Injection
Although in the absence of objects FP doesn't require DI the same way as an OO program would, I've found the use of Protocols has similar needs to that of objects. The Protocol implementation has to be accessible to the function that uses it without explicit dependency on it. In a Java-Spring application the application context would do this wiring, as well as instantiating the proper implementation based on the content of a property file. Lacking any framework I created a dedicated namespace for it, called registry. All namespaces where functions need to call Protocols import the registry namespace. I don't know how others do this, but this solution seemed straightforward.
7. Modules
I kept the module structure of the Java version intact. Game, Table, Player and Cashier are the same, they interact with each other in an asynchronous way. Clojure Async does this job perfectly. There is a channel for Domain Events and subscriptions for the event handlers. Much shorter and cleaner than the Java version's was.
To be continued...
1. Aggregates
First of all Clojure strongly encourages working with immutable data structures. My naive assumption had been that an OO aggregate can be simply substituted with a data structure accompanied by a handful of functions operating on it. This is only partially true. Though I've found state mutation easily replaceable with creating a new data structure (Clojure's persistent data structures make it performant, and its very effective data manipulation functions easy) as the output of the applied function, but I'm not convinced about how invariants should be preserved in the absence of an entity with mutable state. To some degree it can be achieved by :pre and :post constraints on the individual functions, but I haven't really dived into it.
2. Domain events
Related to the previous point, since in OO aggregate roots are to publish domain events. Initially I implemented my "aggregates" the same way, the functions operating on them published events as a side-effect. But eventually I've realized it's very non-FP, so instead of invoking a side-effect, I changed these functions to return not only the updated data structure (the new state of the "aggregate"), but the event-list as well. Then the new "state" is updated in the DB and the events are sent out. This solution (which could be applied in OO as well) eliminates the need of thread-local/event store-flushing magic I resorted to in the java version. I am more than satisfied with this, it's not only idiomatic, but makes things so much simpler.
3. AOP for locking
This is quite pleasing also. Instead of aspects and annotations, it's a 5-(short)-line macro.
4. Layering
The most interesting part. In the very few books mentioning the large-scale structure of FP-programs I've stumbled across the notion of onion-layering, not unlike that of DDD or Hexagonal Architecture. We should strive to confine the mutable states to the outer layers, keeping the core completely functional. Unfortunately in OO-DDD, the "core" is the Domain, which does have logic with side-effects. Repository interfaces and Domain Services as front-doors to ACLs are very much part of the Domain, and are there to enable the Domain to interact with the external world (writing to DB, sending messages, calling web services, ...).
So quite early it became clear that the layering in FP-programs requires some changes in the OO-way of thinking.
4.1 Hexagonal Architecture
If we forget about DDD temporarily and reach back to HA (which I think is one of the foundations of the former), some parallels with the FP-version of onion-layering are obvious. In HA, the Adapters are outside of the core and the Ports are the joints that bind the Adapters to the core. Even an FP-program must interact with the external world (otherwise what's the point of writing it), so HA, with its explicitly designated areas of external interaction seems to be a natural fit.
4.2 Application layer
Having a clean facade for an application has nothing to do with OO or FP, so keeping this layer of DDD seemed ok. In addition to the normal DDD application layer responsibilities, such as locks, transactions and orchestration, I decided all calls to secondary (driving) ports should happen here (calls to a remote Bounded Context, Blackjack Wallet, interacting with the DB). This is the external layer of the onion (still beneath the adapters-layer, though).
I've kept different namespaces in this layer for the different modules (Player, Table, Game) and used most method names for commands with bangs.
4.3 Core (Domain) layer
A purely functional layer. I've tried to simply port the java version's Domain here, minus the secondary (driving ports), e.g. the Game-, Player-, TableRepository or the WalletService, which I've decided to put under a port package on the same level as app and domain. Secondary ports neither defined (but in their own package) or used (but in app services, see previous point) here.
4.4. Infrastructure layer
Quite the same as in the java version. Adapters are implemented as Records of Protocols, see next point.
5. Using Protocols for secondary ports
I've tried to avoid OO-techniques as much as possible, but protocols simply seem to be the right way to implement ports.
6. Application Context and Dependency Injection
Although in the absence of objects FP doesn't require DI the same way as an OO program would, I've found the use of Protocols has similar needs to that of objects. The Protocol implementation has to be accessible to the function that uses it without explicit dependency on it. In a Java-Spring application the application context would do this wiring, as well as instantiating the proper implementation based on the content of a property file. Lacking any framework I created a dedicated namespace for it, called registry. All namespaces where functions need to call Protocols import the registry namespace. I don't know how others do this, but this solution seemed straightforward.
7. Modules
I kept the module structure of the Java version intact. Game, Table, Player and Cashier are the same, they interact with each other in an asynchronous way. Clojure Async does this job perfectly. There is a channel for Domain Events and subscriptions for the event handlers. Much shorter and cleaner than the Java version's was.
To be continued...
Friday, 16 May 2014
Clojure practice - 2
After finishing the previous post I noticed that Kaloz's solution was a bit more concise, not leaning on a helper function. So here is a "more compact" version, even puttin the number->characters mapping definition in the same expression.
or, purely for the sake of example, having even the println in it
(defn compact-combinations [number]
(let [num->chars { \2 "ABC" \3 "DEF" \4 "GHI" \5 "JKL"
\6 "MNO" \7 "PQRS" \8 "TUV" \9 "WXYZ"}
red-fn (fn [acc d]
(m/match (num->chars d)
nil acc
chs (for [c chs
i acc]
(str i c))))]
(reduce red-fn [""] number)))
(println (compact-combinations "34"))
or, purely for the sake of example, having even the println in it
(let [combinations (fn [number]
(let [num->chars {\2 "ABC" \3 "DEF" \4 "GHI" \5 "JKL"
\6 "MNO" \7 "PQRS" \8 "TUV" \9 "WXYZ"}
red-fn (fn [acc d]
(m/match (num->chars d)
nil acc
chs (for [c chs
i acc]
(str i c))))]
(reduce red-fn [""] number)))]
(println (combinations "514")))
Subscribe to:
Posts
(
Atom
)