#Code is Data, So Own Your Code!
Other day a co-worker showed me this piece of code and asked me how we could re-write it in a more Scala way.
//generate id based on rule characteristics
if(priceStatusRule && hierarchyRule && markdownRule && lastReceivedDateRule){
priorityId = 1
} else if(hierarchyRule && markdownRule && lastReceivedDateRule && !priceStatusRule){
priorityId = 2
} else if(priceStatusRule && markdownRule && lastReceivedDateRule && !hierarchyRule){
priorityId = 3
} else if(priceStatusRule && hierarchyRule && lastReceivedDateRule && !markdownRule ){
priorityId = 4
} else if(priceStatusRule && hierarchyRule && markdownRule && !lastReceivedDateRule){
priorityId = 5
} else if(markdownRule && lastReceivedDateRule && !priceStatusRule && !hierarchyRule){
priorityId = 6
} else if(hierarchyRule && lastReceivedDateRule && !priceStatusRule && !markdownRule){
priorityId = 7
} else if(hierarchyRule && markdownRule && !priceStatusRule && !lastReceivedDateRule){
priorityId = 8
} else if(priceStatusRule && lastReceivedDateRule && !hierarchyRule && !markdownRule){
priorityId = 9
} else if(priceStatusRule && markdownRule && !hierarchyRule && !lastReceivedDateRule){
priorityId = 10
} else if(priceStatusRule && hierarchyRule && !markdownRule && !lastReceivedDateRule){
priorityId = 11
} else if(lastReceivedDateRule && !priceStatusRule && !hierarchyRule && !markdownRule){
priorityId = 12
} else if(markdownRule && !priceStatusRule && !hierarchyRule && !lastReceivedDateRule){
priorityId = 13
} else if(hierarchyRule && !priceStatusRule && !markdownRule && !lastReceivedDateRule){
priorityId = 14
} else if(priceStatusRule && !hierarchyRule && !markdownRule && !lastReceivedDateRule){
priorityId = 15
}Right way I saw the pattern matching case here, so I wrote this snip of code.
(one, two, tree) match {
case (true, false, true) => println(1)
case (true, true, false) => println(2)
case (true, true, true) => println(3)
case _ => println(4)
}What I wanted represent was the phrase, Given the same predicates, give me the same answer all the times. This follows the Future.value idea, or what the specification says, and represents well the data modelling I had in my head that day.
Then atfer showing off my Scala skills I landed back to earth and starting thinking about my co-worker's question. This turned on a light in my head and and old but important concept, The Code should own the Data, on very good Code is Data, Data is Code style. I got back to the keyboard and wrote a few lines of code and, what about this?
scala>:paste
case class ruleone(one : Boolean, two : Boolean) {
def isRuleOne() = { one && two }
}
val ruleone(true, true)
scala> val r1 = ruleone(true, true)
r1: ruleone = ruleone(true,true)
scala> r1.isRuleOne()
res2: Boolean = trueThis is a much more interesting way to encapsulate the predicates that I had, and return the same answer all the times. After all, there are other advantages in this practice too:
- You have the logic designed in a modular style
- That can be composed when you need.
- Easily hand over the design, in this case a case class, in a jar, sub-project, or whatever, to someone who has the same questions (or predicates) and needs the same answer all the times
The snip of code above is not actually the final version of the code that eventually is going to Production but sparked the discussuons in other groups where they have similar needs.
##References
- Thanks Big Mike for bringing the question that made me write this article.
- Source (from Mike): http://www.scala-lang.org/old/print/book/export/html/107.html
Really good topic to think about!
I have a question: with the second solution don't you loose the pattern matching capability ending up writing still the below chain of if-then-else (for the problem described above)?
Am I missing something?