31 May 2016
A little bit about UI and UX
User interface and user experience is a very complex topic. There are many things which influence how user perceivesS UI. Many small pieces which aren’t part of the core domain, but sometimes have huge impact at
final result. If everything is fine, then user even won’t notice that, but if something is wrong with this little piece then it will stand out like a sore thumb.
One example of that is correct noun flexion. Especially in language like Polish, because we have rather than complex flexion rules for nouns based on count. In order to provide proper user experience in application we should try to present content in correct grammar form.
Let see how we can use F#
to help us with that task.
Identifying rules
To keep example simple, we will take a look on words in masculine. Yes, the rules are sometimes a bit more complicated ;)
So, below in table, for one example is listed how it should be declined:
Count |
Word flexion |
0 |
wydatków |
1 |
wydatek |
2-4,22-24,32-34,… |
wydatki |
5-9,15-19,25-29,… |
wydatków |
10-14,20-21,30-31,… |
wydatków |
We can use feature from F# to name those rules and make easier for creating functions that will be using those rules. That feature is called Active Patterns
.
Active patterns
They are used to state frequent patterns that we use in pattern matching. But they also can act as a way for make complex patterns shorter.
We can leverage active pattern feature to express our rules in following way:
let (|RuleForZeroAndFromFiveToNineAndTens|RuleForOne|RuleForTwoThreeAndFour|RuleFromElevenToNineteen|) n =
match n with
| 0 -> RuleForZeroAndFromFiveToNineAndTens
| 1 -> RuleForOne
| i when i >= 2 && i <= 4 -> RuleForTwoThreeAndFour
| i when (i % 10 = 1 && i % 100 <> 11) -> RuleForZeroAndFromFiveToNineAndTens
| i when (i % 10 = 2 && i % 100 <> 12) -> RuleForTwoThreeAndFour
| i when (i % 10 = 3 && i % 100 <> 13) -> RuleForTwoThreeAndFour
| i when (i % 10 = 4 && i % 100 <> 14) -> RuleForTwoThreeAndFour
| i when i % 10 >=5 && i % 10 <=9 -> RuleForZeroAndFromFiveToNineAndTens
| i when i > 10 && i < 20 -> RuleFromElevenToNineteen
| i when i % 10 = 0 -> RuleForZeroAndFromFiveToNineAndTens
I could squash some rules together but I think there’s sense to leave it in such a way because it will be easier to maintain. It is simple as it looks, based on given count we compute which rule we should apply.
Using active pattern
Having stated our rules as active pattern, we can easily create function which will help us to display proper form on the UI. Let’s see how it can be done:
let wordDeclination wordForZeroAndFromFiveToNineAndTens wordForOne wordForTwoThreeAndFour wordForElevenToNineteen n =
match n with
| RuleForZeroAndFromFiveToNineAndTens -> wordForZeroAndFromFiveToNineAndTens
| RuleForOne -> wordForOne
| RuleForTwoThreeAndFour -> wordForTwoThreeAndFour
| RuleFromElevenToNineteen -> wordForElevenToNineteen
Thanks to active patterns we do not have to convolute method with logic that is responsible for selecting appropriate word flexion. Entire core logic is hiden in active pattern declaration.
Using function wordDeclination
we can further create small helper functions which will give a word in correct form. There is one important thing to be aware, here arguments order matters, because take a look if we will move n
argument at the beginning then we won’t be able to apply currying to n
argument. It should be clear if you look how we can use function wordDeclination
:
let forUIWydatekDeclination = wordDeclination "wydatków" "wydatek" "wydatki" "wydatków"
Here, we partially applied wordDeclination
function in forUIWydatekDeclination
function. As a result forUIWydatekDeclination
takes one argument and it is count of items. Looking again at function wordDeclination
, if we didn’t move the n
argument at the end, then we would have to provide also n
argument for forUIWydatekDeclination
function. We didn’t do that, so n
argument is curried. We can use forUIWydatekDeclination
in following way:
forUIWydatekDeclination 22
Summary
You may think that this is not rocket science, but as I said earlier those things influence overall user perception about application. Of course you could do that using different manner.
But I think this is neat and clean use case for active patterns.
27 April 2016
Introduction
Since some time, I have been struggling with one problem regarding pipe operator. Sometimes, I’d like to use intermediate values
arising when pipeline is processed. So, previously I was just splitting entire pipeline and create values from those intermediate values using let
binding.
Study case
Let’s take a look at this simple example. We want to split list at place where the highest number appears. So, my previous approach for that was something like this:
let inputList = [5;6;7;8;9;10;4;3;2;1]
let index =
inputList
|> List.indexed
|> List.maxBy (fun value -> snd value)
|> fst
inputList
|> List.splitAt index
However, recently I had some sort of breakthrough. I’ve realized that consecutive steps in pipe are just ordinary functions.
Definition of pipe operator follows :
val inline ( |> ) : arg:'T1 -> func:('T1 -> 'U) -> 'U
It takes left argument and applies it to right function which takes argument with the same type as left argument of pipeline operator. So, what we are actually passing to pipe operator on the right is function. And actually what we have in our F#
toolset are lambda functions, and they are just functions without binding name to it.
For instance, we can create function using lambda functions, but assign name for it using let
binding:
let identity = fun x -> x
The same, we can when we are composing our pipeline. However, there are some nuances. Because we don’t have to use parentheses to declare lambda function I thought that arguments, which lambda function takes, are immediately available for the rest of pipeline. Unfortunately that’s not true. So, that’s what I tried first:
[5;6;7;8;9;10;4;3;2;1]
|> fun inputList -> List.indexed inputList
|> List.maxBy (fun value -> snd value)
|> fst
|> fun max -> List.splitAt max inputList
But I got an error
The value or constructor inputList is not defined.
That actually makes sense if you know that F#
uses indentation to mark scope boundaries.
It’s better to spot when we add parentheses to lambda function
[5;6;7;8;9;10;4;3;2;1]
|> (fun inputList -> List.indexed inputList)
|> List.maxBy (fun value -> snd value)
|> fst
|> fun max -> List.splitAt max inputList
Now, we can see that inputList variable is only visible inside lambda function. So, we can add parentheses to subsequent pipeline steps to make them part of this lambda function and allow inputList variable to be visible.
[5;6;7;8;9;10;4;3;2;1]
|> (fun inputList -> List.indexed inputList
|> List.maxBy (fun value -> snd value)
|> fst
|> fun max -> List.splitAt max inputList)
Hmm, but it’s not looking that sexy, because now List.index inputList
expression puts new identation context at which we must ident subsequent expressions of this function.
However, there’s an exception regarding infix operators, you can offset them from the actual offside column by the size of token plus one, so in that case previous code snippet looks like this:
[5;6;7;8;9;10;4;3;2;1]
|> (fun inputList -> List.indexed inputList
|> List.maxBy (fun value -> snd value)
|> fst
|> fun max -> List.splitAt max inputList)
Back to the topic, what we can do to improve our code’s appearance and still be able to access intermediate values from pipeline?
We can move first expression of lambda function to newline and that would mean next expressions in that function must be indented the same as that line. Take a look:
[5;6;7;8;9;10;4;3;2;1]
|> fun inputList ->
List.indexed inputList
|> List.maxBy (fun value -> snd value)
|> fst
|> fun max -> List.splitAt max inputList
But now, we break how pipeline looks like, and I feel this is not intuitive. We can take advantage of previously mentioned exception for infix operators. Anyway, I feel it is improved a litte bit but still doesn’t solve the issue.
[5;6;7;8;9;10;4;3;2;1]
|> fun inputList ->
List.indexed inputList
|> List.maxBy (fun value -> snd value)
|> fst
|> fun max -> List.splitAt max inputList
I feel the most comfortable if we ident lambda function expressions a bit to explicitly denote that they belong to that function
[5;6;7;8;9;10;4;3;2;1]
|> fun inputList ->
inputList
|> List.indexed
|> List.maxBy (fun value -> snd value)
|> fst
|> fun max -> List.splitAt max inputList
We can do one more thing to get rid of last lambda function, we can define helper function flip
which does one simple thing. It allows to flip arguments which will be passed to given function. Finally, pipeline looks like this
let inline flip f x y = f y x
[5;6;7;8;9;10;4;3;2;1]
|> fun inputList ->
inputList
|> List.indexed
|> List.maxBy (fun value -> snd value)
|> fst
|> flip List.splitAt inputList
Summary
We’ve seen how we can reuse intermediate values from pipeline using lambda functions.
Of course these are not all possibilities of how you can write that pipeline. I hope you will find something useful here, but just use a way that you feel more comfortable with.
16 March 2016
It’s been some time since I wrote last post. I hope, now I will be able to write posts more often. Although, it is getting warmer here in Poland, so hiking and cycling will be possible :)
Functional paradigm everywhere
Nowadays, functional paradigm is quite popular. Java
has got some features known from functional languages as well as C#
. There’s assumption that functional programming is a way to solve problems we have now in object oriented programming. You can find some blog entry, video tutorial, workshop, presentation everywhere, where someone is talking about how to approach your code by functional programming.
Many people think that functional programming is about immutability. But it is not. You can have immutable types also in C#
or Java
. You don’t have it out of the box, but it is possible. Even more, immutability appeared many years ago, for example Eric Evans in his blue book was talking about immutable value objects and how they help to build code, which is easy to maintain and work on. Not to even mention about advantages when it comes to parallelism.
Being functional means composing higher order functions of small functions. Those functions are so small that we can test them easily and quickly.
How we learnt OO ?
It seems that we had similar situation before, when object-oriented programming had its time. It was introduced as a better solution than procedural programming. Do you remember how at university we were first introduced to procedural programming and then to object-oriented programming? At the beginning each of us was writing procedural code using object-oriented language. And still many of us are. They introduced us to object orientation in such a way that we have Shape
and from Shape
we can derive Circle
, Rectangle
and so on. And we believed that this is the root what object orientation is about. How to define data in reusable way, that they share common characteristics and how to leverage inheritance. However, we suddenly get into problems like Fragile Base Class using this approach.
It’s not possible to write generic code that it will handle every cases, is it?. To be honest, think a while how it’s easy to explain such an approach to OO even to your mum. Because it’s similar to what we have in our life. Every rectangle is a shape, isn’t it? This is the same reason why they explained to us in such a way at university.
Another view at OO
For a while let’s back to Alan Kay (considered by some as father of object-oriented programming) famous sentence:
It’s all about messaging.
There is another view at object-oriented systems. Key is to focus on how objects communicate with each other. What messages they send? Object can receive message, takes parameters and send message to another object or return response. It’s easy to understand when you take a look at Smalltalk
language because there notion of sending messages is explicit. For me it’s quite different view from that one focusing on the structure. I think it’s better because it makes that we think in terms of objects. And then objects are not only holders for data. They play their own roles, they have their responsibilities. They must have their state encapsulated properly, because inproper messages can corrupt object. Proper naming becomes then much more important. Names of objects must reflect what role objects play and must reflect domain. Then it’s easy to reason about it.
When you are looking at OO system using messaging approach, then you realize how important principles like Tell Don’t Ask or Law of Demeter are. To be honest, SOLID rules become more clear. And they pretty good fit to this view.
Learn by one’s mistakes
So now I also got a little bit into functional programming. It’s very entertaining for somebody so far familiar with OO languages. I like description that functional programming is about defining recipes for our data. And after that composing functions to perform interesting behavior for us. And those functions are so small that we can test them easily and quickly in REPL environment. This is a huge advantage that we can play with functions at REPL. Also thanks to immutability which is built-in into functional language, compilers can make some additional steps to compile such code to executable code. To be honest, I’m amazed by functional programming. I’m trying to play with Haskell, to learn functional programming correctly. I don’t want to make the same mistake as with OOP, because it took me some time to understand benefits of it (or that’s what I think - as always it is opinionated view). At the end of the day, ultimate goal is to write idiomatic functional code without heritage from OOP.
14 December 2015
LINQ
has been in .NET from 3.5 version. It simplifies a lot many tasks, allowing expressing data processing in more declarative manner. You probably had an occasion to use Except
method. But, do you know exact workings of Except
method?
At MSDN we can find that :
public static IEnumerable<TSource> Except<TSource>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second
)
Produces the set difference of two sequences by using the default equality comparer to compare values.
Having above information, do you have any idea, what would be written into the console when following code is executed?
var invalidChars = Path.GetInvalidFileNameChars();
var fileName = "Availability";
var sanitizedFileName = new string(fileName.Except(invalidChars).ToArray());
Console.WriteLine(sanitizedFileName);
If you initially thought that output will be Availability you are wrong. This is also I thought at first. But there is subtle point in MSDN
explanation of Except
method. It would treat sequences as sets. That means there will be no elements in output sequence from second sequence. This is no surprise. But this also means that every element from the first sequence, which appears more than once, will be omitted in result.
To achieve required behavior, we need a method that would produce the difference between two sequences, so we can do:
public static IEnumerable<TSource> Without<TSource>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second)
{
if(first == null)
{
throw new ArgumentNullException("first");
}
if(second == null)
{
throw new ArgumentNullException("second");
}
return WithoutIterator(first, second);
}
public static IEnumerable<TSource> WithoutIterator<TSource>(
IEnumerable<TSource> first,
IEnumerable<TSource> second)
{
var withoutElements = new HashSet<TSource>(second);
foreach(var element in first)
{
if(!withoutElements.Contains(element))
{
yield return element;
}
}
}
Summary
Except
method is little misleading. When we read the example with sanitizing file name, I bet most of us think that the only invalidChars
will be removed from fileName
. It is good to know that to avoid further confusion. And if we do not want to treat sequences as sets we could always resort to the method like Without
which is shown above.
05 December 2015
Exercises that are intended to check your knowledge of language or teach something about it are called Koans. For example you can find koans for JavaScript language here.
Often, I find that applying solution to some problem later turns out that it was a design pattern. So, I thought that it would be good to describe the context of a problem and leave it to figure out the solution as an exercise for you, dear reader. As the mentioned koans contain tests which initially fails, I will try to do the same and also create a suite of tests which should tell you if your solution is good.
Problem context
Let’s assume that we use domain event pattern for notifying about events in our system. This is also handy when we want to use Event Sourcing. We have a domain event definition that is simply marker interface and looks like this:
public interface IDomainEvent
{
}
We also have an interface for event handlers which are used to mark implementation that will handle these events:
public interface IEventHandler<T>
{
void Handle(T domainEvent);
}
But, new requirement shows up and we need to introduce a MassTransit library because in the near future we want to use queue messaging system to reliably deliver domain events. So we change our IEventHandler<T>
definition to implement IConsumer<T>
interface from MassTransit
.
public interface IEventHandler<T> : IConsumer<T> where T : class, IDomainEvent
{
void Handle(T domainEvent);
}
Now, we can use our event handlers along with MassTransit
.
You can find entire solution here. There is a simple console application that uses MassTransit
to send messages over bus and shows that everything works. There are also unit tests which initially fails (tests are written using NUnit 3). The first failing test states that IEventHandler
for UserCreated
event should not be assignable from IConsumer<T>
MassTransit
interface. The second test states that DomainModel should not have any references to MassTransit
library.
Why bother?
In spirit of the Ports and Adapters architecture we should try to make our domain context independent. Using interface that we do not own from external library make the domain polluted with infrastructural concerns. Also that domain is not reusable if we want to switch to another message library. New domain module, that deals with events must also take dependency to MassTransit
. What we learned in blue book, is that we should isolate domain model from other code.
Summary
Every craftsmen who would like to become better must practice, as we can read in Manifesto for Software Craftsmanship. Therefore, I strongly encourage you to fork, and try to change the code to make all tests pass. As you know I designed it to apply design pattern to solve the problem. However, this is not only solution, that you may think of. But I designed it having in mind a particular design pattern, so that’s why I called it ‘design pattern koans’.