Cymen Vig

Software Craftsman

Day 47, part two: Getting testing up to date on internal project with Backbone.js

I spent the evening playing catch up on the testing for the Backbone.js version of the internal project. All of the collections, models and views are now tested. I was able to apply the approach used by Mike in Childermass in testing and it turned out to be straight forward with Jasmine and Sinon.

I didn’t get a chance to sit down with Mike on Friday. I wanted to discuss with him the approach used in test-driving Backbone.js application development. The problem with doing that as a beginner is that the architecture of the application is in flux. When starting out, it isn’t uncommon to change the approach and this can be done fairly quickly however testing it would increase the time for the learning curve. But maybe there are aspects I’m missing and maybe that increased time is worth it. We do have some new features for the internal project so I will develop them test-driven now that the architecture is clearly defined.

One thing that was beneficial was keeping in mind Mike’s advice: try to get away from the DOM as quickly as possible. With CRUD views this isn’t always easy however it is possible to extract the collecting of the model attributes from the DOM into a single method in most instance. That makes it possible to mock that method with Sinon so that only one or two tests actually have to operate at the DOM level.

It all adds up to 66 specs that are taking approximately 3/4 of a second to run in a recent version of Chrome on Linux.

Comments and Reactions

What is an apprenticeship?

As a child I spent my summers working on a farm. Friends of my family had two dairy farms in Wisconsin: a smaller biodynamic farm (the first in the USA) and a larger rotational grazing (New Zealand-style) farm owned by one of the daughter’s of the original farm and her husband. I had the chance to witness first hand how the apprenticeship model worked. I’m going to try to summarize what I saw in an accessible way in order to discuss apprenticeship again in a later post.

The beginning

At first the farmer can’t trust that the apprentice has enough experience to handle the full operation of the farm. So the new apprentice works closely with the farmer for several months and gradually the apprentice is trusted with more responsibility. There is a huge benefit to both sides: the apprentice gains knowledge and as the farmer begins to trust the apprentice the workload for the farmer goes down. Dairy farming is very labor intensive. The farm I worked on relied on having apprentices in order to have a decent quality of life. So there was a high value to this model for both sides.

The middle

During the middle phase of the apprenticeship the farmer can trust the apprentice to do most of the work on the farm. There may be one or two things that they haven’t quite mastered but if the farmer was suddenly called away for a morning the apprentice would be able to stand in and get things done. The apprentice now spends more time working alone and again as experience is gained typically trust deepens.

The end

Towards the end the farmer can trust the apprentice with the day to day operation of the farm. Some annual things are not part of the apprenticeship but if things are going well, the farmer can now leave the apprentice to manage the farm for a couple of weeks while they go on vacation. This is a huge amount of trust and the apprentice experiences a huge amount of pressure. They are now responsible for the whole farm. If the farm has 100 cows that is basically $150,000 worth of cattle. The apprentice needs to carefully observe the cows to ensure that the vet is called in the case of sickness and they also need to operate the farm as the farmer did on almost the same schedule (cows are very used to schedules – they expect to be fed and milked at roughly the same time every day and production suffers if the schedule gets too far off).

What is an apprentice?

It is someone that you personally have worked with day after day and gotten to know well enough to develop sufficient trust that you would place your livelihood in their hands. They do not yet have the knowledge that comes with the experience of being a farmer year after year. But they do know what you do well enough to be able to stand in for you. They know your cattle, they know your milking system, they know how to operate your machinery, and a whole lot more. The way they gained this knowledge is working with you on the same task. They way they perfected this knowledge is by repeating the task and receiving feedback. They also know your personal philosophy which helps them understand why you do certain things.

What can do wrong?

From either side:

  • Personality conflicts

  • Difficulty forming trust

  • Communication issues

As an apprentice:

  • The farmer may work in a style that is in conflict with that of the apprentice. For example, the farmer may prefer to rush at the last minute to get things done while the apprentice prefers to work at a slower but more steadier pace. The tension here can cause a lot of conflict.

  • The farmer may have expectations of the apprentice that do not match the apprentice. An example of that is expecting the apprentice to have more experience than they do.

As a farmer:

  • Trust with the apprentice may develop slower than desired. It is hard handing over responsibility in all areas.

  • Methods used by more experienced apprentices may be different than those used by the farmer.

  • Unclear expectations may be put upon the apprentice. For example, if the farmer trusts the apprentice to manage the farm for couple weeks while they are gone on vacation they may also leave a list of things to be done if there is time. The apprentice may feel they need to accomplish most of the list yet there are going to be things that come up while operating the farm that are unexpected. That combined with the stress of having the whole operation on their shoulders means there is precious little time in the day for any extra work besides getting the essential chores finished.

Conclusion

A key part of apprenticeship is formal training. The apprentice values this formal training because they can build upon it to become a craftsman (in this case, a farmer). The craftsman values having an apprentice because it is beneficial in the long term in the form of reduced workload. Between the two the experience of sharing knowledge and having to question it in order to teach it has continual value. The world changes. Agriculture has experience this lately in the form of genetically modified seeds and using growth hormones in cows to increase milk production. Less controversially, farming has changed dramatically with modern machinery. With the apprenticeship model the craftsman is faced more deliberately with change. I would argue they also can react to this change more effectively because there is the benefit of both the craftsman and the apprentices questioning the best approach.

Comments and Reactions

Day 47: Beginning to grok Backbone.js, more progress on catching up with testing...

Beginning to grok Backbone.js

Backbone.js is starting to make sense. At first, everything seemed simple and it mostly was. But then I started needed to render an edit view of a model and I tried to do this in place (tied to the same DOM element) as the display view. This created all kinds of problems with events. The symptom of the problem with events was that an event would be triggered once for the first edit attempt. Then the next edit attempt would trigger it twice. And it snowballed from there into a gigantic event storm. This matters because an event might POST an update to the server.

What does one do about this? Well I know that Backbone binds a view to DOM element. When we swap between the detail and edit views we’re attempting to bind to the same DOM fragment. Instead of doing this, why not use a different DOM element and hide/show the two elements based on the current view?

That didn’t quite work… However, I also know that when we create the edit view and it is bound to the DOM element that is when the events are also bound. Now that we have two separate elements when edit is clicked check if we already created. If so, just render it again don’t create it again. This works great and the code looks like this:

1
2
3
4
5
6
7
8
  ...
  if (!this.editView) {
    this.editView = new ...View({el: '#xyz', model: this.model});
  }
  this.$el.hide();        // hide the display element
  $('#xyz').show();       // show the edit element
  this.editView.render();
}

Is there a better way to do this? Maybe… But this is fairly simple and straight forward.

More progress on catching up with testing…

As mentioned in my last entry, the last iteration on the internal project had some testing left undone. I’ve been working on catching up on the testing. That is going well – with Backbone.js all of the controller actions now return JSON instead of a rendered view which means I could clean things up at the same time so that unused code and views are removed.

Comments and Reactions

Day 46: Performing the wordwrap kata at 8LU, two month apprenticeship retrospective with Doug

Performing the wordwrap kata at 8LU

I performed the wordwrap kata today at 8th Light University aka 8LU. It went well although I made a minor typo in the final test that caused it to fail to pass. That caused a slight moment of panic but it was quick to fix and recover. Doug has passed down another Kata challenge that sounds even trickier to do within the maximum time of 9-10 minutes.

Two month apprenticeship retrospective with Doug

Doug and I did a two retrospective. We talked about what I’ve done so far and what is next. I’m going to continue working on the internal project for the immediate future and the new Kata. I’m somewhat bummed out as I watch other apprentices skip some of these steps.

We also discussed the progress on the internal project. On our team there is a big urge to complete the iteration even if the stories aren’t truly complete. In the last iteration, one of the stories I’d bartered with Paul to work on after completing the other iteration stories had some loose ends in testing. I’d wavered back and forth on marking it complete and we opted to go with complete. I realize now I should have held it back. I’m getting more of a feel how the iterations and stories shape what is actually accomplished. I do think it would be much more instructive to be working on a project in which the team was not entirely composed of apprentices as we’re somewhat working in a vacuum. Doug is planning on attending the next iteration meeting so hopefully we’ll have more guidance going forward.

Comments and Reactions

Day 45: Backbone.js, Mustache.js templates and Backbone.js Views

Backbone.js

The internal project now uses Backbone.js along with Backbone-Relational.js to manage items and item comments. There is one complication though: the user interface relies on a “pop up” window which is a jQuery UI Dialog window (in other words, it’s not a real pop-up but one within the page that mimics a real popup without some of the annoyances of a real popup). So a lot of the Backbone.js views need to render into this dialog panel instead of using a controller and rendering to the page. The problem with this is that Backbone.js relies heavily on events and one has to unbind events instead of letting Backbone.js manage that (at least I think that is how it is supposed to work). Hopefully, we can figure out an approach that requires less manual work.

Mustache.js templates and Backbone.js Views

Mike’s childermass project has a SimpleMustacheView.js which I’ve used in the internal project. This works great however I ran into one need that I didn’t immediately see the solution to: I want the text attached to the item in a rendered view to be based on multiple attributes of the model. In other words, say the model has two text fields named Identifier and Owner which are not required. If both are populated, I want to show Identifier + “ - “ + Owner but if only one is populated show it.

The solution I came up with is in the view that SimpleMustacheView.js is being inherited from add to the presenterDate function like so:

1
2
3
4
5
6
7
8
presenterData: function () {
  var attributes = _.clone(this.model.attributes);
  var that = this;
  attributes.display_name = function() {
    // logic here to return name as combination of fields
  }
  return attributes;
}

Now the Mustache.js template can have this:

1
2
3
  ...
  Name: 
  ...

The approach I took is to clone the model attributes that are passed to the Mustache.js view. I don’t want to change the actual attributes. This works however it would be nice to be able to define a function in the model that could be called from the view. Then I realized this really is a view requirement so should the model know about it? So I stuck with this approach and resolved to think about it some more.

Comments and Reactions

Using two Logitech keyboards simultaneously with unifying receivers

I have been looking for an affordable split keyboard for a while. When working at a desk, something like the Microsoft Natural keyboard (the classic white one) has a slight split that is nice. But I wanted something I could use while lying down. The most affordable solution seemed to be the Kenesis Freestyle line but the distance between the halves is limited by a short cable. It’s possible to get a longer cable between the two but it is still not far enough apart for me (or at least not far enough for me to risk buying one and finding out it doesn’t work).

A couple of days ago I realized maybe using two keyboards would work by using one for each hand. I tried it with one wireless one and one wired and it was great so I ordered another Logitech K320 keyboard that features the 2.4 gigahertz “unifying receiver” technology along with excellent battery life (more than a year with a pair of AA Duracell alkaline batteries). When I paired the second keyboard I found my typing often came out like this:

1
This is the greatest thingg in the worldd!

When switching from one keyboard to the other duplicate letters would appear. This limited the rate of typing to an unacceptably low rate. However I figured out a trick! If you use two unifying receivers with each keyboard paired to it’s own receiver the problem is gone. The typing speed is now excellent and the lack of cords improves the usability of this setup.

Comments and Reactions

Day 43 and 44: More Backbone.js

I created a view which receives a collection of items. The view dispatches the items to one of three collections and then renders these collections using a collection view.

The application currently uses a jQuery UI dialog window to keep it “all in one page”. The contents of that jQuery UI dialog window need to change so I created an edit view for an item. This works however there are some interesting side effects with the most minimal approach. When editing the 1st item, everything works fine however when editing the second item all items previously edited are updated with the contents of the second item. The problem is that each time the edit view is rendered event listeners are bound. Because the same bit of DOM is used as the container for the jQuery UI dialog the previous events remain bound too. There are a couple of ways to fix this one being using a singleton to handle the view that encompasses the dialog window. I took a short cut and modified the view to clear the bound events.

Comments and Reactions

An interesting detail for those coming to Backbone.js from direct DOM manipulation...

The context is a simple page with two lists named A and B. One can drag and drop items between or within the lists. The drag and drop code comes from jQuery UI Sortable using the “connected lists” option. When I move an item, I want to show on the item the status of the background save. One easy way to do this is to apply a CSS class to the item and that class has styling that shows a background image that has animation.

Now when one uses Backbone.js the code changes. The items in lists A and B are Collections of Models that have Views. This works great! The jQuery UI Sortable code is very simple – the ‘sortstop’ event triggers a ‘drop’ event on the item. The Backbone.js view for the item listens for the ‘drop’ event and if moving between lists removes the item from the old list and adds it to the new collection. The view also handles sending an update request to the server. The view for the collection (the list) also listens for the ‘drop’ event and submits an update with the new sort order for the collection. Some of the code here likely should be in a Backbone.js controller however that isn’t the interesting part.

The interesting part is what happens at the DOM level when you drag and drop between lists. Before Backbone.js, the DOM for the item being moved was removed from the old location and added to the new location. So anything added to that DOM persisted. With Backbone.js, the DOM for the item at the new location is not the same DOM as at the old location (instead, the new DOM is a new render() of the model for the item). The DOM does not persist unless one specifically accounts for it.

The Backbone.js framework is driving the generation of DOM. One can no longer set say a class on an item while it is being moved and expect it to persist unless it is specifically accounted for in Backbone.js. It is entirely reasonable and makes sense but it is an interesting difference between the two approaches.

Minor footnote

This post assumes it is a good idea to reflect the internal saving of the state change to the server in the client UI. It may not be sensible to do so except for the case of failure.

Comments and Reactions

Day 42: More Backbone.js and Liskov Substitution Principle lecture by Uncle Bob

More Backbone.js

I spent the morning looking at the branch of another internal project that uses Backbone.js to accomplish almost the same thing I need to do in the internal project. I’d started down the path of keeping jQuery UI and Backbone.js separate. On page load, I would kick off both and the communication between them would be by events. Another approach is to have Backbone.js be responsible for everything so it would configure and bind jQuery UI sortable to the lists. So far, I’m preferring keeping them separated by events because it seems cleaner to me. In either method, one is grepping the source tree to follow what exactly is going on and on that basis I don’t see one being more optimal over another. But it is definitely something to think about and ponder on a long term basis. In the short term, I’m going to go forward with my approach to see if I hit any snags.

Update: and once I’d gotten to that point it turned out that there is only a couple lines of jQuery sortable code: binding it to the DOM element(s) and triggering an event with some parameters. I could definitely see pulling this into my Backbone.js code.

Liskov Substitution Principle by Uncle Bob

Today’s 8th Light University was a lecture on LSP by Uncle Bob proceded by the word wrap kata in C. Unfortunately, there has been a run on the word wrap kata lately and I’m scheduled to present the same next week. Hopefully everyone can withstand it one more time. There is a slight wrinkle in my version that Doug has directed me towards and in some ways it’s been better having Mark and Uncle Bob do the kata first so I can start at a different point. We’ll see…

Getting back to 8LU, the lecture was interesting as Bob’s lectures usually are. If you haven’t seen one, you should come to the next 8th Light University. All you have to do is reserve (so we can order enough food). Typically, one arrives at or shortly before noon and the lecture is over by around 1:30-2pm at the latest.

Comments and Reactions

Day 41: Finish up the setup of the internal site on production server, more Backbone

Finish up the setup of the internal site on production server

Ben and I completed setting up the internal rails project on a production server. We were mimicking an existing production site that used vlad for production. That was a bit confusing as “rails -T” didn’t show all the tasks plus one of the rake files seemed to be in the wrong location. There is likely some room for improvement there. There were a number of little system administration things  and programming tasks that needed to be done so it took most of the day. We also changed the instance of our application running on Heroku to be a staging server which was interesting without having direct shell access.

More Backbone

I spent some of the morning looking into Backbone and jQuery UI Sortable. I wanted to use both but now Backbone would be responsible for updating the server and so forth. I figured out how to bind a Backbone model to an event triggered by jQuery UI Sortable however I wasn’t too sure of my approach. Mark (another apprentice) and I looked it over. The event is happening on an individual item within a list. Each item is rendered by a Backbone view and the list is also a Backbone view. Mark and I wondered if we could bind to events on the list at a higher level instead of at the item level. We figured out an approach that worked but we are really interested in inter-list events (moving items from one list to another).

I discussed this with Mike (a craftsmen) to get his view on things. He mentioned that his approach is to make Backbone in charge of everything and one thing I might consider is having a Backbone view being responsible for rendering the list and item views. So adding another view layer to the approach. And then having that view be responsible for binding/configuring jQuery UI. We have another internal tool that is doing something similar so I’m going to look at it and see how this problem was solved before. One of the problems with separating responsibilities with events is that how things work can get confusing. One has to make that leap from the triggered event to the listener to trace how the system works.

Comments and Reactions

Trying to game agile iterations from the developer viewpoint: dead end

I really wanted to do a story this iteration on a project but it wasn’t selected by the client. My scheme was to get the current stories done and then pluck it from the backlog but I then learned it doesn’t work that way: in the event more stories are needed for the current iteration it is likely the client will pick from the backlog by their priority. Thankfully, I discussed my interest in a specific story with the client and happily received the offer of being free to work on that story if the other stories are finished. However I’m still left wondering how developers sell the client on plumbing that they really think is important but doesn’t result in a clearly visible change as a new feature would.

How do you sell necessary but unexciting stories?

Comments and Reactions

Day 40: Deploying the internal application, trying out Backbone.js

Deploying the internal application

I paired with Ben for a good part of the day in a big push to get our internal rails application deployed to a production server. The server is running a specific version of ruby and while it does have RVM so in theory one could use any version in practice Passenger running under Apache is going to use a specific version of ruby with global gems for everything. You can install the passenger gem and compile an apache module and then use that in your virtual host configuration in apache but it’s really ugly and a total hack. So we took the easy path and changed our development environment to match production. With the low cost of virtual machines, I think it makes sense to either have a couple of big servers with one running the most recent stable version of ruby or having one for each application if there is only a handful to begin with. On the other hand, maybe we can get the other applications on that server up to a more recent version of ruby and everyone benefits (if I recall correctly, 1.9.3 had some performance improvements over 1.9.2).

This deployment is complicated by the fact we also want to use SSL and authenticate with our google accounts (using OAuth2). We finished the day with the stack working except for redirect issues between the google authentication services and our host preventing any actually usage. Hopefully, it’s just the DNS update for the new server name taking time to propagate.

Trying out Backbone.js

I spent some time today learning more about Backbone.js. 8th Light craftsman Mike Jansen has a project on github named Childermass that has been quite useful:

Childermass is a way to browse GitHub. It dives into the depths of repos and users and plucks out the most interesting information for you to read.

Childermass is largely an experiment with Backbone.js, sitting on top of Rails. The goal is to have a sufficiently complex example of structured, test driven Javascript for people to emulate and use in their next project.

Using Childermass as an example, I recreated the “three list” view of our internal application in Backbone.js. My reason for doing this is that currently the JavaScript code for the view has to manually update the items in the lists after they are edited in a “popup” (really an in page jQuery UI Dialog). There is also a lot of parsing of the DOM going on to figure out what to send to the server. In short, it is trying to do what Backbone.js is doing but it’s painful and it’s more lines of code that have to be tested. It’s also inflexible compared to Backbone.js. For example, say in the list you want to show another field from the item. With Backbone.js, this is a simple change of the template that renders the item. With the DIY approach you’ll likely have a couple of places to make changes and your testing is likely going to need to change.

Comments and Reactions