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.
Showing posts with label Ext JS. Show all posts
Showing posts with label Ext JS. Show all posts

Monday, April 23, 2012

Imperative curlies 6: removing ifs


In last few posts I tried to argue that there is little or no code reuse around for loops.  There is one notable exception, however, the code reuse by adding lots of additional curlies called if statements.   This post contains my thoughts on how to change imperative ifs used in this way.

Often the developer is faced with two obvious options, repeat very similar (but not identical) imperative logic in several places or code the logic in one place and include lots of if statements within this ‘generalized’ logic to handle the differences.  The generalized logic is often a private implementation method with several Boolean parameters.  It is invoked from various public methods which will set the booleans to trigger the needed side-effects within the private method.  Obviously many programming techniques have been developed to avoid such code (Template Method Design Pattern, or even the concept of polymorphism itself),  but still the if statements are often easier to use.

Here is a piece of code taken directly from the open source Ext JS 4.0.7 (fragment of Ext.form.Basic):
01: getValues: function(asString, dirtyOnly, includeEmptyText, useDataValues) {
02:  var values = {};
03: 
04:   this.getFields().each(function(field) {
05:      if (!dirtyOnly || field.isDirty()) {
06:         var data = field[useDataValues?'getModelData':'getSubmitData'](includeEmptyText);
07:         if (Ext.isObject(data)) {
08:             Ext.iterate(data, function(name, val) {
09:                 if (includeEmptyText && val === '') {
10:                     val = field.emptyText || '';
11:                 }
12:                 if (name in values) {
13:                     var bucket = values[name],
14:                         isArray = Ext.isArray;
15:                     if (!isArray(bucket)) {
16:                         bucket = values[name] = [bucket];
18:                     }
19:                     if (isArray(val)) {
20:                         values[name] = bucket.concat(val);
21:                     } else {
22:                         bucket.push(val);
23:                     }
24:                 } else {
25:                     values[name] = val;
26:                 }
27:             });
28:         }
29:     }
30:   });
31:  
32:   if (asString) {
33:      values = Ext.Object.toQueryString(values); 
34:   }
35:   return values;
36: }      
Ext.form.Basic is an Ext class defining base/reusable behavior of Ext Forms.  Ext JS uses the above method internally:
01: getFieldValues: function(dirtyOnly) {
02:    return this.getValues(false, dirtyOnly, false, true);
03: },      
Also,  the last argument (useDataValues)  is not documented, making getValues behave as an old style form submit value retrieval.   Instead of repeating the same logic and providing separate implementations to retrieve only dirty data from the form vs. all the data,  retrieve data using new model semantics vs. using old form submit,  etc, etc,  the Ext library codes the logic once and provides if conditionals within the logic to handle different cases.

Looking at the above snapshot, can you easily see what the code is doing?

The idea or re-implementing the code by the removing the curlies/shortening distance between curlies is somewhat unfair to the reimplementer.  After all the method signature has all these Booleans (or JavaScript truthies),  and I think the API designers had an imperative implementation in mind when defining the signature of this method.  Declarative/functional thinking vs imperative thinking will impact the APIs.

Lets do it anyway!   I am dropping the asString parameter and I will type it as a separate function.  I personally dislike function result set type changing based on the parameters.   Standard function composition can be defined this way:
f: X -> Y
g: Y -> Z
g Compose f: X -> Z

(g Compose f(x)) = g(f(x))
The more I code with JavaScript the more I find that it is more convenient to do this type of composition (compose with function which is aware of the original argument set):
f: X -> Y
g: Y, X ->Z
g ComposePlus f: X -> Z

(g ComposePlus f) (x) = g(f(x), x)
Assume that we have bunch of utilities coded for things like flexible array concatenation, and that the ‘getFields()’ method returns a rich JavaScript collection object loaded with nice methods like map, fold, filter.  My imaginary filterIf(condition, fn) method will return original collection if condition is not met and filter otherwise.  So here is the new version of the code:
01: getValues: function(dirtyOnly, includeEmptyText, useDataValues) {
02:   var dirtyOnlyAdjustF = function(field) { return field.isDirty(); };
03:    
04:   var fieldRetrievalF = useDataValues ? 
05:                           function(field) {return field.getModelData(includeEmptyText);} :
06:                           function(field) {return field.getSubmitData(includeEmptyText);};
07:
08:   
09:   var emptyFieldAdjustF = function(data, field) {
10:      Ext.iterate(data, function(name, val) { 
11:         data[name] = (val === '') ? field.emptyText : '';
12:  }                                                                          
13:      return data;
14:   };
15:
16:   if(includeEmptyText) {
17:      fieldRetrievalF = FunctionUtil.composePlus(emptyFieldAdjustF, fieldRetrievalF);
18:   }
19:
20:   var foldingF = function(data, aggregator) {
21:      Ext.iterate(data, function(name, val) {
22:        var bucket = aggregator[name];
23:        aggregator[name] = bucket ? ArrayUtil.concatenate(bucket, val) : val;  
24:     }
25:   };
26:     
27:   var values = this.getFields()
28:                      .filterIf(dirtyOnly, dirtyOnlyAdjustF)
29:                        .map(fieldRetrievalF)
30:                          .fold({}, foldingF);   
31: },
32:
33: getValuesAsString: FunctionUtil.compose(Ext.Object.toQueryString, this.getValues);
Lots of developers will say that the second code is better because it is fluent.  I think the fluency is more of a side-effect resulting from changing from imperative to declarative programming style.

Looking at the above code,  how easy is to figure out what the code is doing?   Actually the code says what it does, if statements never do that.

Many developers do not like the ternary operator.  I have used it here to emphasize the declarative aspect.   If the distance between the curlies is short, then we are close to being declarative.  I like when the language lets me drop the curlies to emphasize that the code has been sufficiently refactored from the imperative.   In this example JavaScript ternary operator does just that!

I hope the code speaks for itself so I will not say anything more about it.

Tuesday, March 27, 2012

It is imperative to have many curlies

For the life of me, I could not memorize the term imperative programming (opposite of declarative and functional; the staple of traditional Java). I tried everything and nothing worked. In my brain, the word imperative did not want to associate itself with the whole concept. I guess I get it, the term is derived from commanding the computer to do something, but I just could not remember it! That is until I came up with the pun phrase: “It is imperative to have many curlies”.

Everyone is laughing when I tell them that a good programming is about removing curly brackets. Still, I have persisted in my determination and counting the curlies became a new way for me to measure my code.

Obviously, a simple way to achieve code perfection would be to change the language to one that does not have curly brackets, but that is not the point, the curlies may be still there only they would not look like curly brackets… For the sake of this argument, anything that defines a block of code, indentation in Python/CoffeeScript or Ruby’s end keyword is a curly.
The concept is simple, if I implement stuff, I use curlies, if I declare the behavior or use things like functional composition, then I don’t.
Languages like JavaScript and Groovy (GRAILS) are a good to showcase curly evil. Both are hybrid languages in the sense that you can do very imperative style Java like coding or do something else.

Let me start with a JS example. I am using Ext JS 4 in my current project. Ext comes with methods like: AbstractComponent.setDisabled(boolean disabled).

So if you want to add logic to disable/enable buttons, you can write it commending the browser to do your bidding and that would be with curlies. The code would look like somewhat similar to this:
1:  Ext.define('myView' ,{ 
2:   extend: 'Ext.form.Panel’, 
3:   ..., 
4:   
5:   items: [ 
6:      ..., 
7:      { 
8:        xtype: 'button', 
9:        label: 'save', 
10:       ... 
11:     },{ 
12:       xtype: 'button', 
13:       label: 'refresh', 
14:       ... 
15:     }, 
16:     ... 
17:   ], 
18:   
19:   enableDisableControls: function() { //curly! 
20:    //lots of if statements (curlies galore) defining when each button is 
21:    //enabled and when is disabled ... 
22:   } //another curly! 
23:  });

//  remember to add calls to enableDisableControls() each time:
//   -view is opened,
//   -refreshed,
//   -user makes changes to the data, etc, etc. (that is lots of additional curlies!)
//   -repeat the process for next 35 views you need to write...

Instead of this Object Oriented spaghetti, how about this code: (Note Ext JS adds a concepts of mixin to JS.)
1:  Ext.define('myView' ,{ 
2:   extend: '...’, 
3:   mixins: { 
4:    disableEnableOnDirtyState: '...', 
5:    disableEnableOnSecurity: '...', 
6:    disableEnableOnEditMode: '...', 
7:    ... 
8:   }, 
9:   
10:  items: [ 
11:    ..., 
12:    { 
13:       xtype: 'button', 
14:       label: 'save', 
15:       disableIfDirtystate: 'clean', 
16:       disableIfNotSecurityrole: '..._CAN_MODIFY', 
17:       ... 
18:    },{ 
19:       xtype: 'button', 
20:       label: 'refresh', 
21:       disableIfEditmode: 'new' 
22:       ... 
23:    }, 
24:    ... 
25:   ] 
26: });

The declarative definitions of buttons tell the reusable logic in the mixins that the save button should be disabled unless changes have been made to the form (dirtystate=’dirty’) and unless I have a security role allowing me to make changes or create new entries. The refresh button makes no sense for a new entry before it is saved on the backend so it stays disabled until that happens (editmode) … And I can be adding more and more orthogonal declarative conditions for enabling/disabling buttons!

Note the new version of myView is declarative, it does not implement the functionality it needs, it declares it. Also think of testability. Traditional Java code can try to place some disabling/enabling logic in the ancestor creating hard to test fat ancestors. Unit testing enable/disable mixins is very straightforward. (Note to declarative purists: this code has clear side-effects. It has to. The point is, however, that they are clear. ;)

Also note that some logical decoupling needs to happen since all of these orthogonal conditions compete for one boolean (component.disabled) (see Sencha Discussion Forum Post).

Finally a note for Ext programmers: some tweaking to Ext mixin preprocessor might be in order. Unlike SCALA Traits (or even Groovy mixins), constructor (yes, Ext adds constructor concept to JavaScript as well) is not automatically invoked for mixins so if mixin needs to, say, listen to dirtychange event it has problem arming itself.

To me, this approach is clearly a better code reuse, better code maintenance, it is also clearly better for TDD.

There are many other examples that come to mind:
GRAILS/GORM: GRAILS Domain Classes and GRAILS plugins can provide phenomenal examples of declarative programming where simple declarations load lots of functionality without any coding.

SCALA provides a great way of controlling the curlies in the code. If you coding style is very declarative and functional you will be able to code with very few curlies in SCALA.

So are curlies a measure of code quality? I hope to write more posts about my take on curlies soon.

This post continues here: Next Curlies Bashing