Software has two ingredients: opinions and logic (=programming). The second ingredient is rare and is typically replaced by the first.
I blog about code correctness, maintainability, testability, and functional programming.
This blog does not represent views or opinions of my employer.

Monday, May 28, 2012

Imperative curlies 8: Why Am I Writing This Stuff

A bit over one year ago I started working on my first Groovy/GRAILS/lots of Java Script project.  Before, I worked with Java,  C#,  C++ and I was a very, very imperative programmer.  I was so imperative that I even did not know what imperative programming means (I did not know there can be something else out there).

I think I am not the only one who is going trough this change.  I am writing these posts to help myself by clarifying my thoughts on declarative program design and maybe to help someone make the transition I am trying to make.

How did my first Groovy or Java Script code looked like?  Obviously I jumped to using closures ASAP,  but using closures for the sake of using closures does not create a beautiful code.    I read Groovy in Action by Koning at al.   The book sure showed a lot of cool stuff you can do with Groovy,  but I was still thinking in Java and just applying more groovy syntax when coding.   In parallel to the groovy book,  I read Java ScriptThe Good Parts by Crockford.   Sometime during reading these 2 books,  I realized that to be good in these languages, I need to change the way I think.   I also sensed that, today's programming coolness maxims: dynamic typing, fluent programming, terseness,  are not really it.

Reading the Programming Scala by Wampler and Payne was a great learning and an eye opening experience for me.  I think I learned more about Java, JS and Groovy reading this book than I learned reading anything else and this book is not even about Java, JS or Groovy.   I think that learning Java made me a better programmer in whatever language I was using in 1997-98.  Learning SCALA makes me a better programmer in any of the languages I am using today (that includes Java, Java Script and Groovy).  To get better in SCALA I will need to broaden my functional horizons and probably will need to learn haskell.   So I have a full queue of reading waiting for me.  That will definitely include reading on haskell and reading more on SCALA.

So why am I writing these posts?  I got fascinated by the benefits of declarative programming.  Yet declarative programming is not something the community pays much attention to. 
If you ask a developer in the next office about what functional programming is about, you may hear a lot about immutable state (great) but declarative aspect is probably not going to make it into the conversation.   
There are many reasons why you may not want SCALA on your next project, but, what I hear a lot is that, developers do not like SCALA syntax, they miss not having curly brackets around function implementations.  This is yet another proof that software community has conditioned itself into imperative thinking.

Most developers want to program in Ruby or Groovy,  few are left who still prefer Java.  The most quoted reasons are the new programming coolness maxims (dynamic typing, fluent programming, and terseness).
One by one, if you drill into these maxims of today, they are all questionable.

Dynamic Typing:  You need dynamic language to have cool features of Ruby and Groovy:   You find a lot of opinions like this.  In particular, my current reading (RESTfull web services by Ritchardson and Ruby - an otherwise excellent book) keeps claiming that the Ruby goodness stems from its dynamic nature. The same stuff can be done equally well or better in SCALA which is, of course, statically typed.

Fluent programming:  One often acknowledged problem with this type of approach is that it is easy to use but HARD to implement.  Somewhat overlooked fact is that immutable collections in a functional language are ready for fluent programming.  Functional programming implies fluent!  Think functional!

Terseness:  Java is bad because it is verbose, Groovy is good because it is terse.  This over-simplifies the issue. Ideally language works towards better code.  The fact that code is short does not mean it is good.  I like when language supports terseness as a reward for doing something right.  SCALA allows you to define short one-liner functions without curlies. This allows for declarative definitions of functions similar to how you would declare a function in math (good).  SCALA or Groovy support of pattern matching is another example of good terse syntax complementing good programming style.   But is the # or ## method name in SCALA such a great thing?
How about Groovy Elvis operator?:  it simplifies the code around handling of nulls.  But then is null such a great language concept?  It has been called a billion dollar mistake by the guy to invented it...  Elvis it is better than nothing, but an even better solution would be to get rid of the concept of null.

As I try to become a better programmer,  I would love to have a rule of thumb on what makes my programs good and what does not.  Declarative programming became such as guide for me.  At least for now.
To make this guide even more explicit I came up with a quantitive measure: count the number of curly braces in your code, the fewer the better.
To me it is not about dynamic typing, fluent programming or terseness.  It is about how declarative my code is.

Sunday, May 27, 2012

Imperative curlies 7: switch statements

My programming is changing.  One of the visible aspects of this change is fewer if statements and more switch statements.  During work hours I program in Groovy and GRAILS, but I think the changes in my coding style are more motivated by reading about functional/declarative programming and SCALA than any reading on Groovy.  Still, I am happy with Groovy,  the language fits my coding evolution very well.
(Side Note:  if Groovy was more functional I might have still liked if statements, ifs are a different beast in functional languages.)

The functional programming concept of pattern matching is something I have learned from SCALA.  Groovy has a great support for switch statements so pattern matching can be implemented in Groovy quite well.
 Here is how I might have coded a year ago  (Test is a class representing a test or an exam, it knows a test score):
01: float score = test.getScore();//some object representing an exam or
                                    a test with a score
02: String grade = null;
04: if(score >= 90) {
05:   grade = "A";
06: } else if(score >= 80) {
07:   grade = "B";
08: } else if(score >= 70) {
09:   grade = "C";
10: } else if (score >=60) {
11:   grade = "D";
12: } else {
13:   grade = "F";
14: }
This might have been my Java code, C# code, or my first Groovy code.  Today I would prefer this code: (The rest of the post is in Groovy.)

01: Closure scoreForA = { Test t->
02:  t.score >= 90;
03: }
04: Closure scoreForB = { Test t->
05:  t.score >=80 && t.score < 90
06: }
07: Closure scoreForC = { Test t->
08:  t.score >=70 && t.score < 80
09: }
10: Closure scoreForD = { Test t->
11:  t.score >=60 && t.score < 70
12: }
13: Closure scoreForF = { Test t->
14:  t.score < 60
15: }

16: Test test = . . .
17: String grade

18: switch(test) {
19:  case scoreForA: grade = 'A'; break
20:  case scoreForB: grade = 'B'; break
21:  case scoreForC: grade = 'C'; break
22:  case scoreForD: grade = 'D'; break
23:  case scoreForF: grade = 'F'; break
24: }
As per my previous posts, one liner functions do not contribute to the curly count. 
So yes, I have a significant reduction in the number of curly braces. So what are the benefits?
One obvious difference is that I have separated the declaration of test score conditions for different grades from the conditional logic which calculates the grade.   This allows me to manage these independently.  Think of scoreForX closures as instance fields on my grade assignment class, think of them as something that can be set/dependency injected/configured without any changes to the test grade assignment logic itself.

So, to have some fun with this lets define the following:
01: //class defining rages 
02:class Curve {
03: ObjectRange rangeForA 
04: ObjectRange rangeForB
05: ObjectRange rangeForC
06: ObjectRange rangeForD
07: ObjectRange rangeForF
01: //generic function defining score to grade conversion
02:Closure gradeAssignment = {Curve curve, String testgrade, Test t ->
03:   curve."rangeFor$testgrade".containsWithinBounds(t.score)
This code should illustrate the power of the declarative programming (note my conditional grade calculation logic has not changed):
01: def curve = new Curve(rangeForA: (89.0..100.0),
                          rangeForB: (79.0..<89.0), 
                          rangeForC: (70.0..<79.0), 
                          rangeForD: (60.0..<70.0), 
                          rangeForF: (0.0..<60.0))

02: Closure scoreForA = gradeAssignment.curry(curve, "A")
03: Closure scoreForB = gradeAssignment.curry(curve, "B")
04: Closure scoreForC = gradeAssignment.curry(curve, "C")
05: Closure scoreForD = gradeAssignment.curry(curve, "D")
06: Closure scoreForF = gradeAssignment.curry(curve, "F")

07: Test test = . . .
08: String grade
10: switch(test) {
11:   case scoreForA: grade = 'A'; break
12:   case scoreForB: grade = 'B'; break
13:   case scoreForC: grade = 'C'; break
14:   case scoreForD: grade = 'D'; break
15:   case scoreForF: grade = 'F'; break
16: }
I probably should have added a default: handler in my switch statement, but I omitted it for simplicity.

Except for incorrect use of functional terminology (curry) Groovy has done OK in this example.
Groovy gets lots of credit for being less verbose than Java.  I look at this differently:  I like when the language rewards me for doing the right thing.  Groovy has done just that with its cool switch statement. It awarded me with more compact and more readable code, it awarded me for thinking in more functional pattern matching terms.