Friday, April 9, 2010

Getting to TDD for Rails Developers on a Mac

Do you need to be convinced how beneficial it is to have a good suite of continuously running tests being developed alongside your application?  Think less uncertainty, less anxiety, higher quality, less rework, better adaptability to external factors such as version dependencies...etc, etc.  Of course its not panacea or remover of what is interesting and challenging about writing software, but the list of benefits of discipline in this area is enormous, if not in number, at least in value to the project and to your peace of mind.

Getting started in TDD is the hardest thing tho, especially if you're a bit long in the tooth as a developer like me and haven't been brought up starting a project that way.  Or if for some reason you think that coding is a totally creative exercise like painting that involves no more that broad brush strokes of cleverness applied to a wonderfully private white canvas whose purpose is to express to the world how wonderful you are.

I'm not questioning how wonderful you are by the way :-).  That is a given, however you spend your time.  But I charge that TDD will improve the quality of your programming output, so here high level strategy for beginning to  incorporate it into your Rails development workflow.

You will need:-
- to be a Rails developer on a Mac
- an app with no tests or only tests that you know to work (if you have non-working tests, move them away for now)
- This article for instructions on how to configure autotest for 1) Your environment, 2) an app
- Growl installed on your mac

STEP 1 - Rails Installed

Ensure Rails is installed of course.  This is documented all over the Internet and you will hopefully have Rails installed already as it comes installed with Leopard.  I recommend installing it under RVM (Ruby Version Manager) though for better flexibility and safety.  There is an excellent screen cast by Ryan Bates for installing RVM with Rails 3 here.

STEP 2 - Ensure no failing tests

You will presumably be starting this on some Rails app.  I would recommend that you now move all tests out of that app for now, just so that you don't get confused by any failing as you set up your test infrastructure.  The simplest way to do this may be to use Finder to drag the contents of the app's test folder onto your desktop or somewhere else temporary and easy to get to on your system.

STEP 3 - Install the test infrastructure

As mentioned earlier, this article by Philippe Hanrigou gives the best and most complete instructions I have seen for installing AutoTest.  Follow it carefully and you will have a personalized setup that continuously runs all tests in the current app as soon you type "autotest" from the root folder of the app, notifying you of test results thru Growl.  Since you moved all tests away from the current app in the previous step, no tests will run yet, but we're about to change that.

STEP 4 - Re-install the existing tests (or create them) gradually

Starting with the Unit Tests carefully reinstate each test or test file that you extracted in step 3, making sure they work.  If Step 4 went well, every change you make to the test files and folders during this process will trigger your tests to run and show you the results of these via Growl.  

Be warned that the algorithm used by AutoTest to detect changes and rerun relevant tests is not perfect and you may need to trigger the tests manually (by pressing Ctrl-C in the Terminal shell in which the tests are running) from time to time.

STEP 5 - Develop with stress-free(ish) discipline

Once all of your existing tests are back and working and the AutoTest infrastructure is in place, every change you make to your source in your Rails app should trigger relevant tests.  Promise yourself that your tests will always stay running as you work on any app and will run through without errors.  Try to develop tests for at least all critical code as you complete/enhance/repair your app and enjoy a new sense of trust in your code and the quality of your work.

I hope this is useful to you.

Wednesday, April 7, 2010

Rails 3 Beta Roundup

Last night, I gave a presentation to my local Rails User group on what we can expect from the new version of Rails currently in second beta and how you might approach the task of upgrading existing systems using some already excellent resources out there on the web.   Here's the slide...

Wayne

Monday, February 15, 2010

Building Software the New Flexible Way

I like the way the industry of software development has progressed in the last ten years or so in many ways, but one significant area with which I am particularly impressed is the project lifecycle. In the eighties and nineties, massive, expensive and ambitious projects rose and fell everywhere. A software project was like a juggernaught that began with an idea, grew into a grand proposal, proceeded into a giant list of requirements, and from there was expected to progress steadily and admirably through the phases of high level design, low level design, build, test and deliver all through the miraculous coordination of huge teams of people and tremendous complexity. Oh the naivety, the broken hearts, the stress, the shattered budgets and the sour relationships!

Over time many bold and smart figures in the industry have turned the activity of developing software into a much more 'human' enterprise. We have recognized that computer software is so much more malleable than the products born out of centuries of engineering like bridges and buildings. We have had the courage to allow the undecided and the unknown into the process in a way that feels much more natural to us and much less frightening overall. And I believe today's software is better for it.

The modern software process still begins with an idea of course, one that is the seed of the project. That can be anything and, in the business world at least, usually arises from need for a business refinement or new opportunity. This idea broadly sounds like "we would a like a computer system to do [such and such]". Sometimes, a totally brand new computer system small or large is to be purchased and customized and sometimes the requirement is for an existing system to be modified.  In any case, running with the idea leads to a proposal being formulated (sometimes only mentally) stating the overall aims of the project. These parts of the project remain unchanged from the past. The main changes to the project cycle begin next.

The diagram below tries to summarize what happens from here. Notice a few important things about the project flow: (1) At no point do we try to nail down all possible details of the target system before developing. We agree from the outset that the project will be completed over time through a collaborative and iterative process. And (2) Each phase of the project is more similar to the old style of project. The phase has a certain set of requirements that are met by a process of design, deliver, quality control and refined according to feedback. Unlike the past, however - and this is important - quality is built into this process in the form of test-driven development over the low level design. This benefits both the phase and the whole project by guaranteeing quality in the deliverable while facilitating ongoing reqression testing as the product grows. (3) The end of each phase signals a continue-or-not point in the project. Invoices, salaries, etc are ideally paid up until the end of an agreed and delivered phase, but the sponsor always has a) something for their money and b) control over future spending. If phases are well designed, there is also a reasonable chance of useful deliverables coming out of even an aborted project.




Diagram 1:  A very high level summary of new project structure

Sunday, February 14, 2010

DRY

One key principle behind Ruby on Rails is the one call DRY, an acronym for Don't Repeat Yourself.  Expanded, it means that you should never write the same complex piece of code twice, but instead use function definitions and calls.  The main objective behind it is to ease maintenance, by restricting future changes to code to one place instead of multiple as things need to be modified or fixed.

The principle is by no means a new one to software development and has been touted without the fancy acronym outside of Ruby on Rails for many years.   Subroutines in the original assembly languages had this value in mind as did macro definitions C and function and method definitions in many languages.  Class definitions and even dynamic linking could arguably be considered to have some basis in the same idea.

The visible effects of this principle on Ruby code in Rails are multiple.  For a start, method bodies tend to be small and application structure granular.  Reasons for this include the fact that every method that doesn't implement the most primitive of tasks calls at least one other method.  And Ruby's expressiveness and dynamic nature mean that predefined logic can be reused in all sorts of grammatical contexts, such as overridden operators, enumerators, or as overridden basic classes.

Another effect of DRY on Ruby programs related to the above is that method definitions are numerous.  Following the "no repetition allowed" principle in coding means that nearly every non-trivial method's definition relies on an spawns several other method definitions.   A knock-on effect of this for development is that stack traces from Ruby code like that in Ruby on Rails are long and sometimes challenging to follow due to the deep nesting of method calls.

The DRY principle does overall benefit both the application and the programmer in a number of ways.  It forces the programmer to think in a modular fashion, breaking down large problems domain into key atomic ideas.  It results in logic fragments and concepts that are nicely packaged, easily reusable and usually easy to understand.  And it decreases the number of duplicate code changes that need to be made to modify code thereby reducing coding/copying errors.

Most modern languages employ the DRY principle in some form as code reuse mechanisms.  In coding views, fragments of HTML are instinctively packaged into includable fragments such as Rails "Partials".   Most libraries and languages including Javascript and jQuery rely heavily on function definitions.  CSS supports runtime merging of files (and, using SASS, as many Rails developers do, the reusability of styles through "mixins"). In fact, nearly every language or tool implements some mechanism for defining reusable code fragments, not only within an application, but amongst more that one.  The grammatical contexts and semantics for re-use in software development tend to follow a core set of known patterns, but are on these there are many variations.

In general, the DRY principle is every programmer's friend.  If you or someone else may need to design or do something more than once, turn it into a method, class, module, or even plugin/engine.  It might add future value to even portions of your present output, or at least save on headache medication later.

Friday, January 1, 2010

Welcome and Thanks Fellow Software Developers


Welcome to my Software/Web Development blog at last. This is my place to hopefully give something back to the open source software community that has been so invaluable to me in my own work over the years. After many years working in IT and Software, I got asked in 2006 to produce a non-trivial web site/application and decided to take the opportunity to built it using the Open Source framework Ruby on Rails, a choice that would help bring my software skills up to date and ensure the site was able to support the latest web concepts. That has turned out to be a fantastic decision.  While RoR has not quite made web software development drag’n'drop-easy, as we have got used to with desktop programming, it certainly eased the Web 2.0 development learning curve as well as being a fully capable tool for building modern software.
I love the Ruby language too, on which the Rails framework is based and which gives Rails its name. I try to use that for as much of my programming as possible these days, but don't really mind what I use to get the job done.  Having worked in COBOL, Visual Basic, C, C++, ObjectiveC, C# along with many other languages, I have my preference, but avoid limiting myself by language itself.
So here is a place to share what I learn as I work. I hope what I share helps you even remotely as much as everyone’s amazing input into the web software community is helping me especially over the last decade. Thanks to all you talented software developers, communicators and ordinary programmers like me for the sharing spirit that contributes to my productivity.
Cheers
Wayne

Followers