Sunday, February 15, 2009

BDUF...will it ever die?

It feels incredible to leave my consulting days in the past where I had to constantly explain and justify Evolutionary Design in the face of Big Design Up Front cowards.

This past week further cemented my beliefs that hard problems can NOT be solved by design sessions and paper models.

We found a deep seated problem with the strategy we had devised for controlling some hardware we build. There was a work around, but it was not elegant. The elegant solution was going to require some very complex thinking and an innovative UI to drive it all.

After talking through the problem and some solutions for an hour or so, most people were excited about the change, but wary of its complexity. We have our first release coming up in 5 weeks and this was changing the very heart of the system in a radical way.

Despite (or I would say 'because') of the complexity involved. We eschewed long design sessions in favor of a couple of focused tech spikes. One on the UI sense it was using a metaphor that was not common, and one that got the hard logic of the middle tier working.

We drove the whole thing with unit tests. Made several significant course corrections mid-stream, but solved the entire problem in about 3 days of work.

Looking back there was no way to solve this problem by designing it up front. There were simply too many moving parts. Paper designs do not let you eliminate complexity from your mind. But unit tests let you 'forget' about all the tiny decisions you have made and look forward...breaking the monolithic problem you are faced with into a lot of small problems that are all solvable.

What had seemed like a nearly insurmountable problem when talking about it at a white board that first day has been effectively implemented and tested just a few days later. Everyone involved was surprised at how much easier the problem was in the end.

And that is the crux. Evolutionary design tactics using tools like TDD, autotest, and of course our favorite language of Ruby, has allowed us to actually solve the problem rather than sitting around a design tool mentally masturbating on it.

Tuesday, January 27, 2009

Changing Select Box data via Ajax from Rails

I needed to change the items in a select input control in response to the changing selection of another select input control.

So I registered a change event on the first select input control by:


$('#control_strategy').delegate('change', '#control_strategy', function(){
get_possible_durations();
});


The get_possible_durations function is as follows:


function get_possible_durations() {
data = {};
data['control_strategy_id'] = $('#control_strategy').val();

$.get("/control_events/duration_increment.js?" + jQuery.param(data), null, function(data) {
var options = '';
data = eval(data);
$.each( data, function( n ) {
options += '<option value="' + this[1] + '">' + this[0] + '</option>';
} );
$( "#duration" ).html( options );
});
}



This function simply makes an ajax call passing in a single parameter based on the value in first drop down. It then responds to the completion of the ajax call by building an "option list" and replacing the html of the second select input control.

The Controller Method that I call is simply:


def duration_increment
data = durations_for_strategy(params[:control_strategy_id])
respond_to do |format|
format.js {render :json => data.to_json}
end
end


The duration_for_strategy method just builds a nice nested array of the data that I need to show...the important part is:



values = []
.
.
.
values << [pretty_up(last_time_added), last_time_added]


Pairing and Code Quality

A simple reminder...

We are pretty much a pair programming shop...although we have one project that started with a single person and has evolved to be a fairly complicated piece of code.

The developer on the project is very talented but we don't have the same level of testing rigor woven into the rhythm of that project as it in our core development effort. As a result we are seeing late breaking defects that are easy to fix, but annoying to our client.

The fix is going to be bringing that project into our main effort and ensuring that someone is always pairing when work is done on either.

Friday, January 23, 2009

Being a Pro with your tools

One of my team member said something very poignant to me during an annual review this week. When I asked him what I should work on improving this year he asked that all of us make a concerted effort to become more adept with our chosen editor.

I had always thought that my Textmate skills were passable, but after I thought about his comment, I realized how much room for improvement really existed.

So here begins a journey in shortcuts, macros and bundles that will hopefully land me in a more productive stance. Who knows....I might even be dragged into learning VIM...nahhhh.

Sunday, December 7, 2008

Multi-select boxes and Rails

Using a multi select input control to manage a one-to-many relationship in Rails is not hard, but it also was not obvious to me when I first tried to do it.

Have two models that are related as so:

class ControlGroup < ActiveRecord::Base
has_many :control_group_rate_addresses
has_many :rate_addresses, :through => :control_group_rate_addresses
end

class RateAddress < ActiveRecord::Base
has_many :control_group_rate_addresses
has_many :control_groups, :through => :control_group_rate_addresses
end

class ControlGroupRateAddress < ActiveRecord::Base
belongs_to :control_group
belongs_to :rate_address
end


And a fragment of controller code in ControlGroupsController:

def edit
@control_group = ControlGroup.find(params[:id])
@all_rate_addresses = RateAddress.all
end


Along with an html fragment of:
<%= f.label :rate_address_id %>

<%= collection_select(:control_group, :rate_address_ids, @all_rate_addresses, :id, :name, {}, :multiple => true) %>


The part that I didn't get immediately was the ":rate_address_ids" method call.

I also have ajax interaction with this controller that needs to know what items have been selected and make a call back to the server when the multi-select input control changes. I use jquery, but you could do this (although it would be more verbose) without it. The relevent lines are:

var rate_addresses = $.map($("#control_group_rate_address_ids option[selected]"),
function(value) { return $(value).attr('value') });

$.get(device_url(node_id), { "rate_address_ids[]": rate_addresses },
function(data){
$("#device-list-container").html(data);
});


Building the array of selected RateAddress id's was pretty easy using jquery's powerful selectors.

Then I just had to append the [] in the get call to ensure that the parameters came through as an array.

Back in the controller I can just look at the params and pull out the selected rate_addresses and do whatever I wish.

Hope this helps someone else through this little frustration I had.

Saturday, January 26, 2008