Sunday, March 29, 2015

Using events to remove some duplication from an Angular controller

In this post, we'll show how we're dealing with a controller which is less simple than the TrackDetailsPageController shown in previous posts.

This was the code of that controller in which we had already used the techniques specified in the two previous posts (extending Angular resources with behavior and moving logic to simple JavaScript widgets):

Even though most of the logic in this controller had been removed by using four widgets, (activities, dateRange, categoryList and pagination), there was still duplication in the functions that were doing the coordination among widgets (see functions: loadMonthActivities, loadWeekActivities, loadYearActivities, loadCurrentDateRangeActivities, loadNextDateRangeActivities, loadPreviousDateRangeActivities and selectCategory).

A way of getting rid of this code was using events.

We started by publishing a 'DateRange:Changed' event using the Angular's $rootScope.$broadcast from the updateRange function inside the dateRange widget and then added a listener for that event in the controller which loaded new activities every time that event was published. We also added some new convenience helpers to the dateRange widget in order to make it easier to use from the partial.

This was the resulting code of TracksIndexPageController after these changes:

Notice how the functions loadMonthActivities, loadWeekActivities, loadYearActivities, loadCurrentDateRangeActivities, loadNextDateRangeActivities and loadPreviousDateRangeActivities have dissappeared and how this piece of code

was listening to the 'DateRange:Changed' event to reload the activities every time the date range changes.

Next, we did the same for the categoryList widget getting this new version of TracksIndexPageController:

in which selectCategory was gone.

The duplication that we highlighted in the first version of the controller had been removed but there were still some things we didn't like in this code.
  1. We were using strings to identify the events in different parts of the code (the widgets and the controller). This was a case of the magic numbers smell.
  2. Now our widgets weren't simple JavaScript objects anymore because they were using Angular's $rootScope.$broadcast inside. This made their testing a bit more difficult.
We solved the first problem by putting the events identification strings in just one place:

To avoid the second problem and make our code easier to test we created a wrapper on Angular's $rootScope.$broadcast:

This is a fragment of the current tests for the dateRange widget where we spy on eventPublisher to check that its publish method gets called whenever a function that updates the date range is called:

After all these changes this is the current version of TrackDetailsPageController:

Saturday, March 21, 2015

Keeping Angular controllers complexity and size under control by using plain JavaScript widgets

Another problem I found while working on a legacy Angular application last year, was huge controllers with several hundreds of lines.

Most of those controllers contained a lot of procedural code and were doing too much. This made them very hard to test.

In the new Angular application we're currently working on, we're refactoring very aggressively to keep the size of our controllers small.

Apart from the strategy I talked about in a previous post, another technique that is giving us good results is extracting as much logic and state as possible from the controllers by moving related state and logic into small plain JavaScript objects that we call widgets.

This has had a huge impact in the testability of the code and helped us to keep the controllers size and complexity small.

Now I'll show you the results of one of this refactors, so that you can see its impact in a controller.

This is the first working version of a controller that is coordinating the behavior and content of a page showing details about a track. This page contains a map (using OpenLayers) with the polyline of the track on it, some statistics about the track and several charts (plotted using flot library)) to present some data from the track. It's possible to interact with these charts by changing the magnitude represented in their x axis (it can be distance or time):

Notice how there are a lot of functions in the scope which are managing the state of the xAxis variable and getting information about the charts (x and y axis units, selected magnitude for x axis).

We had also this directive for the charts:

which was being passed the selected x axis magnitude and the charts data.

We got to this version of the code after several design changes and quick spikes. Once we were happy with the UI behavior, it was time to stabilize it.

To do it we created a widget in an Angular factory which was a plain JavaScript object in charge of managing the state related to the charts (xAxis variable which was being read and mutated) and accessing the charts data (which were only being read): Notice how the widget is created by passing the track to the create method. This method initializes some values and returns the charts widget which has privileged access through a closure to several private functions and data.

We basically moved all the functions related to the charts that were before in the controller into the new widget and made some of them private.

After being moved to the widget, the logic controlling the charts became very easy to test using fake tracks:

After this change the controller was reduced to this:

Notice how all the chart-managing logic has disappeared from the controller. The only code related to the chart that remains is its creation.

We were also able to simplify the code of the directive by just passing it the new widget:

Notice how the widget has also absorbed the code that produced the points in the chart.

We have continued refactoring this controller and others in the same way. Making small refactors every time we detected duplication or discovered new concepts that could help us extract behavior from them.

This is the current code of the controller that we've been showing in this example:

Keeping Angular controllers complexity and size under control is a constant effort that, having seen in other projects the negative effects of huge controllers, I think it's totally worth it.

Friday, March 20, 2015

Interesting Talk: "Crafted Design"

I've just watched this wonderful talk by Sandro Mancuso:

Avoid primitive-obsession-related problems by adding behavior to Angular resources using Underscore extend function

One of the problems I found while working on a legacy Angular application last year, was resources with deeply nested structures that were being accessed directly from many different places.

That code was revealing too much about the resources inner structure and that meant that the code that interacted with the resources was spread all over therefore generating a lot of duplication. That made it really hard to change and understand.

It was suffering from a severe case of primitive obsession in the form of directly using raw resources.

To prevent that from happening in the Angular application we are developing now, we have added behavior to Angular resources using Underscore extend function. By doing it, we have managed to hide the inner structure of the resources from its users and also created an object that has attracted the resource-handling code that was before spread all over.

These strategy has put us in a much better position. Now if the structure of the JSON data of a resource changes for any reason, we have only one place to go to adapt to that change.

It also has improved the overall readability of the code by making it possible to give proper names to the different resource-handling functions.

Here it's an example from our code:

Notice the use of the extend function to add the behavior in TrackMethods to the prototype of Track resource.

TrackMethods is an object containing several functions that hide the inner structure of the Track resource and make its use more readable: The only restriction we put ourselves is that behavior extensions like TrackMethods can't have any state.

Currently TrackMethods contains only accessors, but it will surely grow as the application evolves. All the functions in TrackMethods were discovered in other parts of the code and moved into it. We try to stay alert at new opportunities to attract more code into these behavior extensions.

Another advantage we've found is that these behavior extensions can be easily tested using fake resources.

These are TrackMethods current tests:

This strategy of extending Angular resources with behavior is an alternative to encapsulate collection which is working quite well for us to avoid primitive-obsession-related problems.

Thursday, March 19, 2015

Friday, March 13, 2015

Mars Rover using a finite state machine implemented with mutually recursive functions and trampoline

I've continued working on the Mars Rover kata.

This time I've solved it using a finite state machine implemented with mutually recursive functions and trampoline.

Mutually recursive functions are a nice functional way to implement finite state machines and it's a functional way of expressing the state pattern (see Functional Programming Patterns in Scala and Clojure, Michael Bevilacqua-Linn).

As in the previous example using protocols, we have four possible states of the rover:
  • The rover is facing north
  • The rover is facing east
  • The rover is facing south
  • The rover is facing west
and we have four valid transitions from each state:
  • Rotate left
  • Rotate right
  • Move forwards
  • Move backwards
which correspond to the commands that the rover can receive.

These states and transitions can be directly translated to a set of mutually recursive functions by associating each state to a function:
  • The rover is facing north -> facing-north
  • The rover is facing east -> facing-east
  • The rover is facing south -> facing-south
  • The rover is facing west -> facing-west
and each transition as a condition to call the next function.

This is the new code of the rover name space:

Notice how inside each of the functions representing rover states (facing-north, facing-east, facing-south and facing-west), there is a case on the command which determines which of the functions will be called next, i. e., which is the next rover state.

Once the next function is selected, we pass it the rest of the commands (notice how destructuring is used to succinctly extract the first command and the rest of commands).

The recursion ends when there are no more commands (command will evaluate to nil), in which case we return the current-rover.

Ok, now some technical details:
  1. Trampoline function. The trampoline function is used in order to make Clojure optimize the mutual recursion.
    Each state function returns a function returning a value (notice the # tacked onto the front of the outer level of each state function) instead of directly returning the value. This is required by the trampoline function so it can manage the stack on the mutually recursive calls to avoid stack consumption for long command sequences.
    To start the trampoline we feed it with the initial state function (given by get-initial-state-fn) and its parameters.
  2. letfn form. Using letfn allows to create local functions which can refer to each other. This can't be done using let because it executes its bindings serially.
The rest of the name spaces have changed also a bit.

The commands name space now just translates from the received character signals to keywords representing each command:

The worlds name space is nearly the same, I just added two helpers (wrap and rover-not-hitting-obstacle) so that the functions that do the wrapping and the collisions with obstacles checking are easier to use in rover name space (they also help to hide the inner structure of worlds):

Finally, the core name space is much simpler now:

I'm using exactly the same tests I used in the three previous solutions:
  1. Kata: Mars Rover in Clojure using multimethods
  2. Separating Mars Rover code into different name spaces
  3. Mars Rover code version using protocols instead of multimethods
so I won't post them again.

You can find the code of this last example in this GitHub repository.

I've discovered this other way of doing this in these two great books: I've learned a lot coding this solution.

Sunday, March 8, 2015

Mars Rover code version using protocols instead of multimethods

I've continued working on the Mars Rovers kata code that I first implemented using multimethods.

In this version I've used protocols instead of multimethods.

Since I had previously distributed the code in several different name spaces, I only had to modify the rover name space.

The rest of the code keeps just using the same functions of the rover name space: the rover factory and the four commands rotate-left, rotate-right, move-forwards and move-backwards.

However, the implementation of the rover name space is quite different now.

This is the new code:

I've defined two protocols Rotable and Movable which are implemented by new four defined records: FacingNorth, FacingSouth, FacingWest and FacingEast.

Depending on the value of the rover direction, the oriented-rover factory function, creates an instance of one of those records.

When one of the command functions (rotate-left, rotate-right, move-forwards or move-backwards) is called, it calls a function with the same name passing it the result of calling the oriented-rover factory on the rover.
This call is dispatched on the type of the record the call to oriented-rover returns, so that, in the end, the right implementation of the function gets called.

This has been a nice exercise to explore and practice with protocols.

I'll continue exploring other ways to solve this kata with Clojure.

You can find the code in this GitHub repository.

-----------

Update: I continued working in this code on Mars Rover using a finite state machine implemented with mutually recursive functions and trampoline

Separating Mars Rover code into different name spaces

I've separated the Mars Rover kata code I started in a previous post into different namespaces.

This is the new directory structure in which there are three new name spaces: commands, worlds and rover. The commands name space contains the code in charge of creating the commands from the messages received:

The rover name space contains the rover factory function and the command multimethods that are applied on rovers:

and the worlds name space contains the code related to wrapping rovers in a world and detecting obstacles: I also simplified the application of commands to the rover in the core name space by using a closure so that the apply-command function captures the world instead of passing it in the reduce accumulator as I was doing before:

I also learned how to use :refer to require only specific symbols from a name space. I'm also using it in the tests (which except for that are exactly as in the previous version of the code).

I think the code has a better structure now.

You can find the code in this GitHub repository.

-----------

Update: I continued working in this code on Mars Rover code version using protocols instead of multimethods and Mars Rover using a finite state machine implemented with mutually recursive functions and trampoline

Wednesday, March 4, 2015

Kata: Mars Rover in Clojure using multimethods

Yesterday we had a coding dojo in Clojure Developers Barcelona meetup.

We practiced together doing the Mars Rover kata.

I had already done this kata in Java and C++ before (several times) using the state pattern to eliminate all the conditionals on the rover direction and the command pattern to decouple the translation from the messages sent to the rover into commands acting on it.

As usual I used a mix of TDD and work on the REPL to code this Clojure version.

To document the process I committed the code after every passing test and every refactoring and also committed the REPL history. You can find the commits step by step here.

After making the rover rotations work I had a huge cond on the rover direction with an if branching on the command value inside each case.

It was time to refactor.

The suggestion in the kata was to try to eliminate conditionals using maps, multimethods and/or protocols.

First, I used multimethods, dispatching on the rover direction and the message it was receiving just to see how multimethods work.

It took me a while to make it work because I had a error in the arity of a defmethod and the stack trace was difficult for me to understand.

Then I realized that it was much better to separate the translation of messages into commands from the commands themselves. To do it I used a map that associate each message to the command multimethod:

Here you can see one of the multimethods:

From here on, coding the remaining commands using TDD was very easy. I just had to write a failing test and then make it pass by implementing its corresponding defmethod.

Once all the possible commands were working, I started with the functionality of wrapping the rover in a world.

If you check the commits, you'll see that I tried several approaches here because I wasn't sure how to model the world.

In the end, I decided to model the world as a map with a :wrap-fn key associated to the wrap function for a given kind of world. I passed the world map as a keyword parameter to the receive function which had a default value equal to infinite-world whose :wrap-fn was the identity function. That way all my previous tests continue to work without having to change them.

Then I started doing TDD to code the wrap function for a kind of world called squared-world which was created by a factory function by the same name.

Finally, I started with the obstacles which were modeled as a list of positions (which were represented by maps like {:x 1 :y 2}) associated to the :obstacles key in the world map.

To code the hit-obstacle? function I used the REPL for the first time (you can check all my tests on the REPL history which I also committed) to try to make it work using the some function.

After that I just added a validation to check if the initial position of the rover was on an obstacle.

These are the resulting tests using Midje:

and this is the resulting code:

I'm not sure if this is a good factorization for this problem in Clojure, (I feel that what I did for having different implementations of the wrap function is still a bit OO-ish), but it was a good exercise to practice with multimethods and start exploring their possibilities.

You can find the code in this GitHub repository.

Next time I'll try doing the same exercise using protocols instead.

I enjoyed a lot this coding dojo.

Thanks everyone for coming and Akamon for letting us use its facilities.

-----------

Update: I continued working in this code on Separating Mars Rover code into different name spaces, Mars Rover code version using protocols instead of multimethods and Mars Rover using a finite state machine implemented with mutually recursive functions and trampoline