Monthly Archives: November 2012

Functional Decorator

Recently I’ve been experimenting with functional programming and Scala. As a developer used to Object Oriented paradigm I was wondering what are the functional equivalents of popular design patterns. One of the best articles summarizing this subject is Mark Seeman’s “Patterns Across Paradigms”. I am currently working on a small project where I had a chance to implement the Decorator Pattern using functional constructs in Scala.

The Object-Oriented approach

My example is be based on “DDD CQRS Leaven”, a project presenting some system and domain modeling concepts. This application was originally created by Sławek Sobótka and Rafał Jamróz, you can browse the codebase on Github. Here we are going to focus only on a small part of the domain, the  Rebate Policy. It’s a simple representation of Strategy Pattern, responsible for calculating eventual rebates for products in an online store. The model of policies can be described in few boxes:

Dead simple so far, right? We have our RebatePolicy contract with a couple of implementations. Now let’s see how it looks like when we add a Decorator:

Here’s the implementation of these components:

Such design allows combining different Domain Policies (Strategies) in a flexible way to obtain object which still matches the RebatePolicy interface and represents the composition. Decorator pattern allows adding new policies and creating various combinations in runtime without modifying existing ones or the “client code”, which keeps using the original abstraction. Neat.

Functional implementation

Trying to achieve similar goals using functional code requires reminding that the GoF Decorator Pattern is, in fact, a supplementary construct required to compensate the shortcomings of typical OO languages. In functional world we can leverage currying and functions as first-class citizens to get same desired effect. Before we explore the functional implementation in Scala, take a look at the RebateDecorator class. It represents an abstract base for all rebates which can wrap other rebates. A RebateDecorator forces our rebate to pass some inner rebate object in the constructor and provides it as a protected member for further use by the inheriting class. Then, the VipRebate class allows creating an instance in two ways: either with some decorated member or without it. Let’s do something similar with functions in Scala:

As you can see, the RebatePolicy type is now a functional type, which means that we speak more directly of our contract: A RebatePolicy is a function which takes a Product, quantity and minimumPrice and returns rebate value of type Money. Standard policy produces a function fulfilling this contract by calculating the rebate with some simple algorithm. What about VipRebate? It’s also a function, but a bit more complex 🙂 In fact, the VipRebate represents kind of a Factory (yes! Another pattern that we get for free!) which allows creating new function of type RebatePolicy with additional parameters: two Money values and innerPolicy. The Option type in Scala gives a way to initialize the rebate with “none” inner policy which is much more elegant than null manipulation that we saw before. Our goal has been achieved with some additional bonuses:

  1. Much more concise. The baroque entourage of Java has been strongly reduced to what’s essential. No more unnecessary ceremony, while the readability and comprehensibility are still high (or even higher). The superfluous RebateDecorator class is no longer needed and it doesn’t “pollute” our real domain logic anymore.
  2. Flexibility. Thanks to currying we have free “functional dependency injection” capabilities. The VipRebate signature allows creating final policy in three steps: first with initial parameters (minimalThreshold, rebateValue). Such call would produce another function which we can pass around and eventually call with optional inner policy argument. This second call will finally produce a RebatePolicy ready to use whenever it is needed. In previous, objective approach we were forced to build our object with all the dependencies right away (with constructor). To achieve more flexibility we would require some setters which breaks immutability and stinks 😉

Consequences

Exploring the world of functional programming is addictive and changes your mindset forever. If you are interested in further learning then you should definitely check the free “Functional programming principles” course on Coursera. First edition just ended but next one will launch probably around spring and you will be more than satisfied 🙂

Advertisements

Warsjawa: Workshops with SoftwareMill

Recently Warsaw JUG organized its 100th meeting, offering 10 different workshops to choose from. I signed up for “One day with a difficult client” organized by SoftwareMill and so did a few of my friends. The workshops were supposed to make us experience typical traps and difficulties set by clients and try to overcome them, so we expected it to be real fun 🙂 Piotrek Buda has already blogged about it. I must also warn you, that following text contains SPOILERS. If you would like to attend such workshops in the future, then maybe jump straight to “Conclusions” and don’t let the rest spoil the surprises.

The setup
The workshop leaders invited us into a short and amusing game to make us better remember our names, feel more comfortable and relaxed. Then we were divided into three groups, ~5 people each. Leaders gave us a short contract describing the task and the teams were separated. From this moment on, each group had to fulfill the contract and cooperate with “the client” who was very well played by people from SoftwareMill 🙂

The task
I haven’t mention it yet but our goal was not related to software at all. In fact, what the contract stated was a very short information, that we have to “build a spacecraft capable of transporting an atomic family into space”. The launch time was scheduled for 12:30, which was around 1.5h after we started. Our group received also a set of tools and materials: cardboard boxes, ducktape, pins, glue, paint, brushes, markers and some other stuff. Our client announced that we were going to work in 15-20 min. iterations and have short meetings with his representatives after each sprint. This was basically the whole briefing and our team had to start working right away.

Up the garden path

So here we are: a “self-organizing”  team of five people willing to build an awesome spacecraft. The specification was intentionally minimal, encouraging us to ask lots of questions and squeeze more information out of our client. Every 20 minutes we had a chance to ask about anything yet we failed big time to get what was actually important. After 2-3 iterations we accidentally discovered that the shuttle will be shot into space by a catapult produced by external company and that successfully mission means that it should pass a distance of minimum 3 meters. Our group totally missed the goal of getting the essential requirements and focusing on client’s real value. Instead we fell into a trap of making the shuttle pretty (colors, colors…) and equipping it with bonus content (like tv or…. pool!). The client did a really great job leading us off the track by happily acknowledging every crazy idea that we proposed. We also easily got caught into meaningless chit chat and almost wasted one whole meeting talking about nothing. In other teams the client also took away their leader for one iteration to paralyze work a little bit 🙂
Before our last iteration we had:

  • A big carton with no idea if it could even fit the catapult
  • Zero tests petformed
  • A detailed plan of shuttle interior including TVs, toilets and a minibar (sic!)
  • Very specific documentation about the colors of every single piece of our shuttle

With a stroke of luck we managed to get some data from tests performed by the owners of catapult and with this data we drastically shrinked our shuttle literally minutes before launching…
Then, the big moment of truth 🙂
Fortunately, the craft passed required 3 meters and our mission succeeded. The moment of launch was breathtaking and we had lots of laugh after 🙂

Retrospection
Another good idea of workshop leaders was to organize a retrospective meeting afterwards and discussing the whole work together. First we learned what are the common problems occurring when working with a difficult client (which is basically any client 😉 Then the organizers told us how they tried to set up similar traps for us, which pretty much worked out very well for them 🙂
Finally, each team presented their insights on mistakes they made and how they overcame certain problems. In our group the most important failures were especially:
1. Losing focus on what our client requires
The contract stated clearly that we need to launch a craft and nothing more. Instead of getting details on the launching process and the flight itself we started to dwell into discussions about how should the craft look like with tons of completely irrelevant information. But hey, the client acted perfectly, pulling us further and further into oblivion 🙂
We learned that it’s extremely important to keep focus on the real needs and values expected by client, especially because he usually cannot clearly name them himself. In this case our job was to precise that he needs to fit a craft into certain catapult and shoot it 3 meters away. That’s it, really. All that could be achieved in 1-2 iterations 🙂
2. Neglecting integration with external system
I had a chance to participate in quite a few projects involving integration with some services hosted (sometimes created simultaneously) by third party companies. I know that it is the most vulnerable point of whole project and at the same time, the most underestimated risk in most cases. This case wasn’t different but I could not manage to convince my team to focus on the catapult and to get as much data and testing as possible. Well, lesson learned once again 🙂 Let me just say this mantra again: you must perform tests with the external system as soon as possible in your project life cycle or you will be screwed and sorry.

Conclusion
Failing is great! Thanks to Ola, Janek and Tomek for letting me “safely” fail this time and learn so much 🙂 There is no conference talk or any kind of theoretical discussion which could make us feel so much knowledge as such workshops with palpable experiences. I’m really surprised how many things we could grasp in such a short time. No matter how agile your team thinks it is, you should try it yourself 🙂