Saturday, 7 May 2016

New version of Principle

After a year long hiatus, I've touched Principle again. A new version is out, 0.34, that moves all configuration from the clunky pom.xml to a neat yaml file, like the one below


root_package: org.tindalos.principle
checks:
layering:
layers: [infrastructure, app, domain]
violation_threshold: 0
third_party_restrictions:
allowed_libraries:
- layer: infrastructure
libraries: [org.apache.maven, org.json, org.yaml, com.google.common.collect, jdepend]
- layer: domain
libraries: [org.apache.commons]
violation_threshold: 0
package_coupling:
cyclic_dependencies_threshold: 0
acd_threshold: 0.35
modules:
# Map modules to packages
module-definitions:
EXPECTATIONS: [domain.expectations]
CORE: [domain.core]
AGENTSCORE: [domain.agentscore]
AGENTS: [domain.agents, infrastructure.reporters]
CHECKER: [domain.checker]
# Define dependencies between modules
module-dependencies:
EXPECTATIONS: []
CORE: [EXPECTATIONS]
AGENTSCORE: [CORE, EXPECTATIONS]
AGENTS: [CORE,AGENTSCORE,EXPECTATIONS]
CHECKER: [CORE, AGENTSCORE]
violation_threshold: 0
structure_analysis_enabled: true
view raw principle.yml hosted with ❤ by GitHub

The next big thing will be to make it usable a SBT plugin, while also retaining the Maven plugin nature. By looking at the documentation of "Simple" Build Tool, this looks challenging.

Saturday, 9 April 2016

The Reader Monad

Yet another exploration in Monadland. Like the State Monad, its sibling, Read Monad had managed to elude me until I came across an enlightening example in Debashish Gosh's excellent book, Functional and Reactive Domain Modelling. In the following example I'll describe a simple scenario where I'd usually use dependency injection and refactor it to a Reader monad using variant.

Version 1. Dependency Injection

case class User(id: Int)
trait NotificationService {
def notifyUserAboutSth(user: User): Unit
}
trait UserRepository {
def find(id: Int): Option[User]
}
class UserService(
repository: UserRepository,
notificationService: NotificationService) {
def notifyUser(userId: Int): Unit = repository.find(userId) match {
case Some(foundUser) ⇒ notificationService.notifyUserAboutSth(foundUser)
case None ⇒ println("No user found!")
}
}
view raw DIExample.scala hosted with ❤ by GitHub
When one tries to follow FP principles, she strives to build her application up like an onion. The core should contain pure functions, and all interaction with external services - DB, web service calls, user input, ... - , i.e. side-effects, should be confined to the outer layer. In the code above the domain logic and side-effects are undisentanglable. The next version shows an alternative.

Version 2. Higher order function

case class Context(userRepository: UserRepository, notificationService: NotificationService)
object UserService {
def notifyUser(userId: Int): Context ⇒ Unit = context ⇒
context.userRepository.find(userId) match {
case Some(foundUser) ⇒ context.notificationService.notifyUserAboutSth(foundUser)
case None ⇒ println("No user found!")
}
}
//build up the computation
val notify: Context => Unit = UserService.notifyUser(joe)
//fire the side-effects
notify(context)
This is better. `notifyUser` is now a referentially transparent function. The actual execution of the effects is deferred to a later point, when the result function is called with the context. The Reader monad is nothing else just a convenient wrapper around such a function.

Version 3. Reader Monad

case class Reader[R, A](run: R ⇒ A) {
def map[B](f: A ⇒ B): Reader[R, B] = Reader(r ⇒ f(run(r)))
def flatMap[B](f: A ⇒ Reader[R, B]): Reader[R, B] = Reader(r ⇒ f(run(r)).run(r))
}
object UserService {
def notifyUser(user: User): Reader[Context, Unit] = Reader { context ⇒
context.userRepository.find(user.id) match {
case Some(foundUser) ⇒ context.notificationService.notifyUserAboutSth(foundUser)
case None ⇒ println("No user found!")
}
}
}
//build up the computation
val notify: Reader[Context, Unit] = UserService.notifyUser(joe)
//fire the side-effects
notify.run(context)
The benefit Reader monad offers over the simple HOF-solution is the monadic composability, like in the example below.

trait AccountService {
def credit(userId: Int, amount: Int): Reader[Context, Unit]
def debit(userId: Int, amount: Int): Reader[Context, Unit]
}
val service: AccountService = ???
val transfer: Reader[Context, Unit] = for {
_ ← service.credit(1, 10)
_ ← service.debit(2, 10)
} yield ()
//fire the side-effects
transfer.run(context)

Note that inside the for comprehension the context doesn't even appear.

Saturday, 12 March 2016

Struggling with the State Monad

After spending hours trying to find articles explaining the damn thing without resorting to "let's take this contrived example..." or "let's take a real life example, generating pseudo-random numbers" (seriously?!), I'm still left with frustration. Eventually I'd reached out to Kaloz, who pointed me to one of his earlier explorations of the topic. His example is here, but I'm still in the dark why is it any better than a simple foldLeft. In the code below I refactored slightly Kaloz's code to keep the generic part apart from the specific solutions. A second foldLeft-using function is provided to match the signature of the function using the State monad, although I don't see any additional value in that.

package org.bluecollar.scalaz
import scalaz.Scalaz._
import scalaz._
object StateMonadExamples extends App {
//Domain and test values
sealed trait Input
case object Coin extends Input
case object Turn extends Input
case class Machine(locked: Boolean, candies: Int, coins: Int)
private def applyInput(i: Input): (Machine) ⇒ Machine =
(m: Machine) => (i, m) match {
case (_, Machine(_, 0, _)) => m
case (Coin, Machine(false, _, _)) => m
case (Turn, Machine(true, _, _)) => m
case (Coin, Machine(true, candy, coin)) => Machine(false, candy, coin + 1)
case (Turn, Machine(false, candy, coin)) => Machine(true, candy - 1, coin)
}
val inputs = List(Coin, Turn, Coin, Turn, Coin, Turn, Coin, Turn)
val machine = Machine(true, 5, 10)
//Implementation with STATE MONAD starts =============
val state = scalaz.StateT.stateMonad[Machine]
def rules(i: Input): State[Machine, (Int, Int)] = for {
_ <- modify(applyInput(i))
m <- get
} yield (m.coins, m.candies)
def simulateMachine(inputs: List[Input]): State[Machine, (Int, Int)] = for {
_ <- state.sequence(inputs.map(rules))
m <- get[Machine]
} yield (m.coins, m.candies)
def simulationWithStateMonad(inputs: List[Input], machine: Machine) = simulateMachine(inputs)(machine)
//Implementation with STATE MONAD ends =============
//Implementation with foldLeft. A 2-(rather short)liner
def simulationWithFoldLeft(inputs: List[Input], machine: Machine) = inputs.foldLeft(machine) { (m, input) ⇒
applyInput(input)(m)
}
//Implementation with foldLeft, where the result is the same format
def simulationWithFoldLeft2(inputs: List[Input], machine: Machine) = {
def convert(m: Machine) = (m, (m.coins, m.candies))
inputs.foldLeft(convert(machine)) { (m, input) ⇒
convert(applyInput(input)(m._1))
}
}
//Test
println(simulationWithStateMonad(inputs, machine))
//(Machine(true,1,14),(14,1))
println(simulationWithFoldLeft(inputs, machine))
//Machine(true,1,14))
println(simulationWithFoldLeft2(inputs, machine))
//(Machine(true,1,14),(14,1))
}
Kaloz? What am I missing?

Saturday, 27 February 2016

What a senior back-end developer should know in 2016


I've been developing software for a decade now and quite often feel overwhelmed by the sheer amount of must-know-s someone needs to possess by common consent to earn the right to be called a professional. I think almost everyone can fail an interview if being asked the wrong questions, regardless of experience. 
I've spent half an hour assembling the following lists. I'm too lazy to elaborate the items here (mostly I just mention some related keywords) or structure them properly, but I think the gist comes through. The items also highly vary in importance and required level of depth. Of course it depends on your field, mine is the Enterprise Java (lately Scala) world. E.g. I've never needed to implement a binary tree in my career, but subjectively consider it somewhat "important". I also simply drop in DDD, but it takes years to master (as opposed to getting sufficiently familiar with HTTP). 

So, here we go
  • Knowing at least one language inside-out
  • Good software development principles:
    • separation of concerns, polymorphism, SOLID principles, encapsulation, loose coupling, high cohesion
    • understanding the concept of good quality code and the capacity to produce it - very vague definition, yet the most important. It has nothing to do with frameworks/technologies/most of the things listed below
  • OO fundamentals. Design patterns, SOLID principles
  • FP fundamentals - it's just getting into the mainstream, but hopefully sooner or later will be ubiquitous
  • Algorithms and data structures ( graph theory, O(n), binary trees, tail recursion, ...)
  • Concurrency, thread safety, parallel computation. Deadlock, livelock, threads, thread-pools, locks, synchronization primitives, CSP, Actor model, Dataflow (Functional Reactive Programming)
  • JVM memory model
  • Monitoring tools (JMX, JProfiler, ...)
  • Dynamic vs static typing, pros and cons
  • DI frameworks (the concept and at least one, e.g. Spring)
  • App servers (like JBoss. The concept at least and pros/cons against lightweight solutions)
  • Build tools (Ant, Maven, Sbt, Leiningen, depends on the language)
  • Testing
    • TDD, BDD, mocks, stubs, load tests, unit testing patterns, integrations tests, acceptance-level tests, non-functional tests, property-based tests, ...
  • Databases
    • Relational
      • Working proficiency with SQL
      • Transactions (local vs distributed), ACID, dirty reads, transaction isolation levels, etc
      • optimistic/pessimistic locking
    • NoSQL - when to use which, pros, cons, etc
    • ORM tools
  • Middleware
    • HTTP protocol
    • Network protocols (TCP, UDP, SSL, ...)
    • Messaging - Enterprise Integration Patterns, JMS or some alternative, ActiveMQ or some alternative
    • REST
    • SOAP (not so relevant any more)
    • Synchronous vs asynch communication. When to use which, benefits and pitfalls.
    • Markup languages - xml, json, yaml, ...
  • Small-scale architecture 
    • packaging, layering principles, cohesion, coupling, static code quality metrics, MVC, UML, Hexagonal Architecture
    • Patterns: pipeline, circuit-breaker, ...
  • Big-scale  architecture
    • SOA, microservices vs monoliths
    • Scalability (vertical, horizontal, functional decomposition)
    • CAP theorem
  • Domain-Driven Design
  • HTML, DOM, Javascript
  • Continuous Integration/Delivery tools
  • Deployment tools (Ansible, Capistrano, ...)
  • Cloud - e.g. AWS
  • Project management methodologies (Scrum, Kanban, ...)
  • OSs
  • Networks
I'm sure I missed some pretty obvious ones...