Tuesday, 31 March 2015

Improving existing code - imaginary checklist - 2

Continuing the completely random and unprioritized checklist. Some of them are easy to fix, some are heavy.

Eliminate mutable state where possible

Immutability has many advantages over mutable objects, none of them will I mention here. For an example see the Query class in the previous post. Avoid setters, use final keyword and defensive copies.

Thread safety

Quite self-explanatory.

Separation of concurrency and domain logic

Multi-threading logic should be separated from the rest of the code. It's quite complex on its own, even more when is intertwined with other things.

Invariants and UnitOfWork-s

Check what are the units of work, and what are the invariants. The formers should encapsulate the latter. This is quite an important point. And a not so low hanging fruit, probably.

Push third-party code to the outer layers

This might be a big one. Practically I think almost all application should follow the Hexagonal Architecture style. This can be achieved iteratively, but could take a long time to get there if the code hasn't been written that way.

To be continued...

Binary Tree implementation in Haskell, Clojure and Scala - 2

And thanks to @Kaloz, here is the Scala implementation with a slightly altered/extended functionality.

object TreeOrd extends App {
implicit val ageOrderting = org.kaloz.twitter.TreeOrdImplicits.AgeOrdering
implicit val carOrdering = org.kaloz.twitter.TreeOrdImplicits.CarOrdering
val personTree = Tree(Person("A", 10), Person("G", 5), Person("C", 2), Person("B", 7))
println(personTree)
val carTree = Tree(Car("Trabant", 40), Car("Porsche", 300), Car("Opel", 150), Car("Skoda", 100))
println(carTree)
}
case class Person(name: String, age: Int)
case class Car(name: String, maxSpeed: Int)
object TreeOrdImplicits {
implicit object AgeOrdering extends Ordering[Person] {
def compare(a: Person, b: Person) = a.age compare b.age
}
implicit object CarOrdering extends Ordering[Car] {
def compare(a: Car, b: Car) = a.maxSpeed compare b.maxSpeed
}
}
object Tree {
def apply[A](elements: A*)(implicit ordering: scala.math.Ordering[A]): Tree[A] = {
elements.foldLeft(EmptyTree: Tree[A])((sum, item) => sum.insert(item))
}
sealed trait Tree[+A] {
def insert[B >: A](elem: B)(implicit ordering: scala.math.Ordering[B]): Tree[B] = this match {
case EmptyTree => Node(elem)
case Node(v, l, r) => v match {
case _ if ordering.lt(elem, v) => Node(v, l.insert(elem), r)
case _ if ordering.gt(elem, v) => Node(v, l, r.insert(elem))
}
}
}
case object EmptyTree extends Tree[Nothing]
case class Node[A](value: A, left: Tree[A] = EmptyTree, right: Tree[A] = EmptyTree) extends Tree[A]
}

Improving existing code - imaginary checklist - 1

I endeavour to prepare a checklist I would go through if I had to start to work on a brownfield project. Small things to improve, hunt for the low hanging fruits. Don't expect any enlightenment here, these are just pearls of blue-collar wisdom.

Handling unrecoverable exceptions

In my current project we use messaging via ActiveMQ. Should an exception occur, the message is bounced back to the queue, then retried. It's fine, as long as there is a chance of recovery and sometimes - for example when the message is invalid in some way - there is none. In this case bouncing the message back is a waste of time and resource, plus the message can and up in the Dead Letter Queue leading to memory loss. So instead we should catch these exceptions as close to the entry point as possible and simply log them.

Validating input

Related to the previous point. To adhere the fail-fast principle, the inputs of the system should be validated. Validation is usually against some domain criteria, so I would put the logic in the Domain layer, just as the input passed the ACL. Should the input fail to comply, throw an unrecoverable exception.

Validate domain objects

I wouldn't stop at the inputs. I'd validate every domain object upon creation. Design by contract is a very good practice.

public class Query {
private final String queryId;
private final PlayerSession playerSession;
private final SearchOptions searchOptions;
public BuddiesQuery(String queryId, PlayerSession playerSession, SearchOptions searchOptions) {
Validator.isTrue(StringUtils.isNotBlank(queryId));
Validator.isNotNull(playerSession);
Validator.isNotNull(searchOptions);
this.queryId = queryId;
this.playerSession = playerSession;
this.buddySearchOptions = buddySearchOptions;
}
//getters
view raw Query.java hosted with ❤ by GitHub
The validation should throw an unrecoverable exception. See the first point.

To be continued...

Tuesday, 24 March 2015

Binary Tree implementation in Haskell, Clojure and Scala

I've embarked on learning Haskell recently. I only start to suspect the power of this language, but I'm already impressed with its beautifully succinct and readable, no-nonsense syntax. Nuff' said, let's do a demonstration!

Haskell

data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show)
treeInsert :: (Ord a) => a -> Tree a -> Tree a
treeInsert x EmptyTree = Node x EmptyTree EmptyTree
treeInsert x (Node a left right)
| x == a = Node a left right
| x < a = Node a (treeInsert x left) right
| otherwise = Node a left (treeInsert x right)
treeElem :: (Ord a) => Tree a -> a -> Bool
treeElem EmptyTree _ = False
treeElem (Node y l r) x
| y == x = True
| x < y = treeElem l x
| otherwise = treeElem r x
buildTree :: (Ord a) => [a] -> Tree a
buildTree xs = foldr treeInsert EmptyTree xs
view raw binaryTree.hs hosted with ❤ by GitHub

Clojure

(ns clojure_study.ideas.tree
(:require [clojure.core.match :as m]))
(defn node [val left right]
{:value val :left left :right right})
(defn tree-insert [x t ord]
(m/match t
:empty-tree (node x :empty-tree :empty-tree)
{:value val
:left left
:right right} (condp = (ord x val)
:eq t
:gt (node val left (tree-insert x right ord))
:lt (node val (tree-insert x left ord) right))))
(defn tree-elem? [x t ord]
(m/match t
:empty-tree false
{:value val
:left left
:right right} (condp = (ord x val)
:eq true
:gt (tree-elem? x right ord)
:lt (tree-elem? x left ord))))
(defn build-tree [elements ord]
(reduce #(tree-insert %2 %1 ord) :empty-tree elements))
;;an ord function for numbers
(defn num-ord [x y]
(cond
(= x y) :eq
(> x y) :gt
(< x y) :lt))
view raw binary-tree.clj hosted with ❤ by GitHub

Scala - I've failed with this one. Maybe @Kaloz can help me out.