Archive for the 'project' Category

My first woodturning commission

This week a colleague approached me to ask if I could make something for him.
His house, which he’s been renovating, still had an original doorbell from whenever it was built. The door bell was a round metal plate with a button in the middle, inset into a wood ring which was screwed to the wall.
Time had not been kind to the wooden ring and it was a rotted mess.


So the job was simple, could I make him a replacement wooden ring.

The challenge for me was whether I could actually make a replacement quickly enough to make the job worth while. After all there is a limit to how much anyone is going to pay for a wooden ring. I agreed a price of £10, and figured it would be up to me to make that worth while for me.

Of course, since this is my hobby, I don’t have worry too much about earning a certain amount per hour of work. But I didn’t want to sell my time cheap either.

I had given him the choice of a couple of woods that I knew I had in the garage, and he chose American white oak, since he has used oak throughout the renovation of his house. I’d hoped that what I had would be the right size. Sadly however I was forced to make up a blank by gluing two blocks together. This required some time to make sure the edges were square and flat, and of course some drying time.

Whilst it was drying I decided to play around with a piece of scrap wood. I mentally stopped the clock for this, since I could have just gone back inside and continued later.

I didn’t wait too long, the glue gave a good enough hold quite quickly. Once I thought it was ready, I used the bandsaw to cut the corners off and generally get it to about the right size. I also ensured my centre was just to one side of the glue line. I figured it wouldn’t be very apparent on the finished piece, and I didn’t want to jam my drive centre straight into the glue join and risk forcing it open.

I turned between centres to rough it to round, and turn a spiggot, then switched it into my 4 jaw chuck for actual shaping.

It wasn’t very difficult to do, face off the front to a flat, then measure the diameter of the recess, and carefully used the skew chisel as a scraper to mark the line, I approached it from intentionally too small, taking a series of wider cuts to get the right size.

Shaping the exterior curve was just a matter of holding up the old one in eyeline of the new, and judging by eye where to adjust the shape of the curve.

Then boring a hole through the middle was a case of using the spindle gouge to get the depth with straight-ish sides, just shy of the right diameter. Then again using the skew chisel as a scraper, to get the right diameter.

The finished result I’m pretty happy with, when seen side by side with the original.


I’ve asked for pictures of the before and after with it in situ, so I’ll update when I’ve got them.

As for how long it took, I think I spent a little over an hour working on it. Now I’m not fast, but I’m not that slow either. Some things just take time. I wonder how a professional woodturner can possibly make a living! I guess they turn much higher value items, that have a better time/value ratio.

Turning a burr

Burrs are very interesting bits of wood. They are odd growths that occur on the surface of tree trunks. I’m fascinated by what causes them to occur, since they are basically a mass of knots. Wikipedia on burrs

Burrs typically have all sort of faults within the wood. But the wood is so dense both physically and visually in terms of grain patterns, that you can turn something quite beautiful, faults and all.

At the Hampshire woodturners meetings I go to, I’ve seen a number of examples of really great burr pieces. Of all shapes and sizes, which have often inspired me to consider trying myself. But I rarely justify buying myself more wood pieces when I have so much that I could do with what I already have.

However, recently Kat took a trip to turners retreat, and among the things she brought me back was a piece of burr. I have no idea what tree it’s from, there was no label to say, and I guess it doesn’t really matter.
It’s a fantastically odd looking thing:

My first reaction was ‘where do I start?’

I decided I wanted to make a bowl, but attempt to leave a cross section of the original exterior just beneath the rim of the bowl. I’ve seen examples of this approach, and I like the way you get a feel of the original burr exterior cross cut through the smooth sleek finished bowl.

To mount between centres I first used a forstner bit to drill a hole in the face side, roughly central, and just a little wider than my drive centre.

This was so the drive centre would be locked in place and there is now way this thing would fly off once the tailstock pinned it in position. I brought the tailstock up to try to have the bulk of the burr fairly central. Obviously I wanted the most material centred as possible to get the biggest bowl I could in the shape. Regardless there was a large growth off on side of the bottom that I just had to turn away.

I turned the rough shape of the bowl at the bottom, leaving enough left to be able to shape a little top ‘rim’ for the bowl and keep a sliced cross section. This was fairly tricky, To begin with the whole thing is quite out of balance, and once you are preserving the cross section your turning without constant contact to the wood, so it’s very difficult to get a good cut.

After quite a lot of time, and a few catches that could have been disastrous but were ok, I wound up with the outside profile done.

Unfortunately, or perhaps fortunately, the most centred position for the bowl meant not such a central cross cut of the original exterior, and so it is rather one sided. I’ll kid myself that this is part of the natural effect I was going for.

You can just about see here that one side of the bowl wall is actually the original exterior, I could have tried to turn it away, but again most of the point of these shapes is to preserve the interesting faults.

Having shaped the outside I sanded and finished, before turning to re-chuck on the spigot that I turned on the base.

I didn’t take any pictures of the hollowing process. I used my spindle gouge to do most of the hollowing, but then used a small bowl gouge to get the final cuts on the inside. I also used a scraper to finish under the rim. This was a last minute decision, as I was hollowing I decided to leave the rim a little wide and give an undercut.
As I hollowed I found one of the faults ran from the outside to the centre, leaving me with a hole in the side. But I’m ok with that.

It’s not easy to see, but I tried to leave a downward curve on the cross section. It ended up being quite a subtle effect, mostly because it’s quite hard, and partly because as I did it I was aware that if I took away much more material I’d weaken some of the smaller sticking out bits too much, and either risk snapping them, or be forced to turn even further to remove them completely.

I spent quite a lot of time sanding down grades, and trying to get a good surface. The ‘wing’ on the cross section in particular I spent some time with a sanding arbour in my drill working down grades to smooth out the fairly rubbish surface I’d left with my not so great tool skills. Ultimately I did quite of lot of hand sanding to try to lose any scratches and avoid just rings left by sanding with the lathe on. I also spent a fair amount of time applying wood wax, and trying to get a streak free finish. This mostly involved giving it time to cure a little, and going around with my lamp shining to show off the surface, and using a buffing pad to work away to a smooth surface.

Having satisfied myself with that finish, I removed the bowl from the chuck and put it to one side. Whilst I turned a jam chuck to remount the bowl so that I could turn away the spigot.
At this point I have enough bits of scrap around that I happened to have an off-cut of oak with a spigot already on, that was just about right. I turned a domed end on it, and then put 4 or 5 layers of kitchen roll in the bowl to protect the surface as I remounted it. Again bringing the tailstock up to it’s original mark at the base of the spigot.

I was pretty pleased that it turned pretty much right back on centre. Which made life much easier as I very gentle turned away the spigot, being careful to take small cuts. I did cause the lathe to stop a couple of times, but mostly my cuts were light enough to not be a problem.

I turned the spigot down to a small pin of wood, then worked on finishing the base. I turned a slight recess curve to ensure the bowl will sit flat on it’s rim. I also refined the curve at the base of the bowl to turn into base a little, which I hope gives it a slightly ‘lifted’ effect when finished.

The last step was off the lathe, slicing the last pin of spigot away with a sharp chisel. I was very careful here, really didn’t want to slip and gouge finished surface.
Once it was pared down as much as possible with the chisel, I sanded by hand the bottom, from 120 grit in all steps down to 1200 grit. Then a very small amount of wax on the base.

And finally it’s finished!

Ultimately, despite the time I put into finish, I’m still not that happy with it. I obviously need to learn more about applying wax finishes. I suspect I need much more patience between stages for a start. But with limited time that can be difficult.

That said, I am pleased with how the overall process went. I didn’t have any real frustrating slips, and it came out as planned, without me having to adjust to cover up mistakes.

Kat took some better pictures of the bowl

Witter – a basic python twitter client for Maemo

So I wrote last week about developing a basic twitter client. And this week I got the main stuff done, and wanted to share the code example here.

In my looking for help developing apps for Maemo from a start of basically no GTK knowledge or python knowledge I found the examples either too trivial, or way over engineered. So I wrote this intending it to be useful (to me), contain only enough capability to basically read my timeline and tweet. I’ve intentionally not added bells and whistles (yet) and it’s a single ‘monolithic’ app. By which I mean it’s all in a single python file, there is no separation of gui and logic, no nice engineered constructs etc etc.

I hope that it does show an intermediate level example of writing an application for Maemo using Python. This is what it looks like in action

Witter

This was taken full screen. The app supports switching in and our of full screen. And it adjusts the width of the displayed text to fit. As you can see the shot was taken not long after completing the application.

It also sorts the tweets using the ListStore ability to just tell it which column to sort on. This is very useful as it means I don’t have to mess around myself. Originally I had it sorting on created_at, but since I was loading that as a String it would order Thursday below Wednesday. Rather than cast the string into a meaningful date object of some form, I just used ID instead, which is a Long. Still comparing as a string, but the number always increments so newer tweets always appear t the top.  Obviously if you prefer newer tweets at the bottom, just flip the sort order to Ascending.

So here is the code, it’s a little under 300 lines, but I’ve commented it pretty well (I think) to explain what it’s all doing.

# ============================================================================
# Name        : witter.py
# Author      : Daniel Would
# Version     : 0.1
# Description : Witter
# ============================================================================

#This is the bunch of things I wound up importing
#I think I need them all..
import gtk
import pygtk
import hildon
import urllib2
import urllib
import base64
import urlparse
import simplejson
import socket

#Initially I found I'd hang the whole interface if I was having network probs
#because by default there is an unlimited wait on connect so I set
#the timeout to 10 seconds afterwhich you get back a timeout error
# timeout in seconds
timeout = 10
socket.setdefaulttimeout(timeout)

#the main witter application
class Witter(hildon.Program):
    #first an init method to set everything up
    def __init__(self):
        hildon.Program.__init__(self)
        #being lazy this just uses basic auth and I am not doing anything
        #yet to store uid/pwd so for the moment just put info here
        self.username = "YOUR_USERNAME"
        self.password = "YOUR_PASSWORD"
        #This being a hildon app we start with a hildon.Window
        self.window = hildon.Window()
        #connect the delete event for closing the window
        self.window.connect("delete_event", self.quit)
        #add window to self
        self.add_window(self.window)
        #For this app I wanted a scrollable area for the tweets to show up
        #so I create a gtk ScrolledWindow
        self.scrolled_window = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
        # as well as somewhere to show the tweets we need somewhere to write a tweet
        # this being twitter we cap the input at 140 chars
        self.tweetInput = gtk.Entry(max=140)
        # we also want a couple of control buttons to load up tweets and submit a tweet
        self.buttonloadTweets = gtk.Button(label="Load Tweets",stock=None, use_underline=None );
        # we connect out load tweets button to the getTweets method
        self.buttonloadTweets.connect("clicked", self.getTweets)
        self.buttonnewTweet = gtk.Button(label="Tweet",stock=None, use_underline=None );
        #we connect the Tweet button to the newTweet method
        self.buttonnewTweet.connect("clicked", self.newTweet, self.tweetInput)
        # a vertical box to set the scrollable window and the button box
        # in the display
        self.box1 = gtk.VBox(False, 0)
        #a horizontal box to put our tweet input box and two control buttons in
        self.buttonBox = gtk.HBox()
        # add the Vbox to the window
        self.window.add(self.box1)
        # create a menu object by calling a method to deine it
        menu = self.create_menu(self.scrolled_window)
        # add the menu to the window
        self.window.set_menu(menu)
        # define a liststore we use this to store our tweets and some associated data
        # the fields are : Name,nameColour,Tweet+timestamp,TweetColour,Id
        self.liststore = gtk.ListStore(str, str, str, str, str)
        # create the TreeView using treestore this is the object which displays the
        # info stored in the liststore
        self.treeview = gtk.TreeView(self.liststore)
        # create the TreeViewColumn to display the data, I decided on two colums
        # one for name and the other for the tweet
        self.tvcname = gtk.TreeViewColumn('Name')
        self.tvctweet = gtk.TreeViewColumn('Tweet')
        # add the two tree view columns to the treeview
        self.treeview.append_column(self.tvcname)
        self.treeview.append_column(self.tvctweet)
        # we need a CellRendererText to render the data
        self.cell = gtk.CellRendererText()
        # add the cell renderer to the columns
        self.tvcname.pack_start(self.cell, True)
        self.tvctweet.pack_start(self.cell,True)
        # set the cell "text" attribute to column 0 - retrieve text
        # from that column in liststore and treat it as the text to render
        # in this case it's the name of a tweeter
        self.tvcname.add_attribute(self.cell, 'text', 0)
        # we then use the second field of our liststore to hold the colour for
        # the 'name' text
        self.tvcname.add_attribute(self.cell, 'foreground', 1)
        # next we add a mapping to the tweet column, again the third field
        # in our list store is the tweet text
        self.tvctweet.add_attribute(self.cell, 'text',2)
        # and the fourth is the colour of the tweet text
        self.tvctweet.add_attribute(self.cell, 'foreground', 3)
        # we start up non-fullscreen, and we want the tweets to appear without
        # scrolling left-right (well I wanted that) so I set a wrap width for
        # the text being rendered
        self.cell.set_property('wrap-width', 500)
        # make it searchable (I found this in an example and thought I might use it
        # but currently I make no use of this setting
        self.treeview.set_search_column(0)
        # Allow sorting on the column. This is cool because no matter what order
        # we load tweets in, we always get a view which is sorted by the tweet id which
        # always increments, so we get them in order
        self.liststore.set_sort_column_id(4,gtk.SORT_DESCENDING)
        # I don't want to accidentally be dragging and dropping rows out of order
        self.treeview.set_reorderable(False)
        #with all that done I add the treeview to the scrolled window
        self.scrolled_window.add(self.treeview)
        # Then just 'pack# the scrolled window and a Hbox into the
        # V box
        self.box1.pack_start(self.scrolled_window, True, True, 0)
        self.box1.pack_start(self.buttonBox, False, True,0)
        #and pack the hbox with input field and buttons
        self.buttonBox.pack_start(self.tweetInput, True,True,0)
        self.buttonBox.pack_start(self.buttonnewTweet, False, False,0)
        self.buttonBox.pack_start(self.buttonloadTweets, False, False,0)
        #setup some urllib things to use to fetch twitter feeds
        self.last_id=None

    def quit(self, *args):
        #this is our end method called when window is closed
        print "Stop Wittering"
        gtk.main_quit()

    def create_menu(self, widget):
        #a fairly standard menu create
        #I put in the same options as I have buttons
        # and linked to the same methods
        menu = gtk.Menu()

        menuItemGetTweets = gtk.MenuItem("Get Tweets")
        menuItemGetTweets.connect("activate", self.getTweets )
        menuItemTweet = gtk.MenuItem("Tweet")
        menuItemTweet.connect("activate",self.newTweet)
        menuItemSeparator = gtk.SeparatorMenuItem()
        menuItemExit = gtk.MenuItem("Exit")
        menuItemExit.connect("activate", self.quit);
        menu.append(menuItemGetTweets)
        menu.append(menuItemTweet)
        menu.append(menuItemSeparator)
        menu.append(menuItemExit)
        menuItemFile = gtk.MenuItem("File")
        menuItemFile.set_submenu(menu)
        return menu

    def run(self):
        #this is the main execution method
        # we set things visible, connect a couple of event hooks to methods
        # specifically to handle switching in and our of fullscreen
        self.window.show_all()
        self.window.connect("key-press-event", self.on_key_press)
        self.window.connect("window-state-event", self.on_window_state_change)
        #this starts everything up
        gtk.main() 

    def getTweets(self, *args):
        #Now for the main logic...fetching tweets
        #at the moment I'm just using basic auth.
        #urllib2 provides all the HTTP handling stuff
        auth_handler = urllib2.HTTPBasicAuthHandler()
        #realm here is important. or at least it seemed to be
        #this info is on the login box if you go to the url in a browser
        auth_handler.add_password(realm='Twitter API',
                          uri='http://twitter.com/statuses/friends_timeline.json',
                          user=self.username,
                          passwd=self.password)
        #we create an 'opener' object with our auth_handler
        opener = urllib2.build_opener(auth_handler)
        # ...and install it globally so it can be used with urlopen.
        urllib2.install_opener(opener)
        #switch on whether this is an refresh or a first download
        if self.last_id == None:
            json = urllib2.urlopen('http://twitter.com/statuses/friends_timeline.json')
        else:
            #basically the twitter API will respond with just tweets newer than the ID we send
            json = urllib2.urlopen('http://twitter.com/statuses/friends_timeline.json?since_id='+str(self.last_id)+'L')
        #JSON is awesome stuff. we get given a long string of json encoded information
        #which contains all the tweets, with lots of info, we decode to a json object
        data = simplejson.loads(json.read())
        #then this line does all the hard work. Basicaly for evey top level object in the JSON
        #structure we call out getStatus method with the contents of the USER structure
        #and the values of top level values text/id/created_at
        [self.getStatus(x['user'],x['text'], x['id'], x['created_at']) for x in data]

    def getStatus(self, user,data, id, created_at):
        #at this point user is another JSON structure of lots more values of which we are currently
        #only interested in screen_name
        #append to our list store the values from the JSON data we've been passed for a tweet
        # the funny #NXNXNX type values are colours I chose a slightly blue for the name
        # and black for the tweet. At some point I intend to do some alternating colours for
        # cell backgrounds to make the display clearer
        self.liststore.append([ user['screen_name'],"#2E00B8",data+"\nposted on: "+created_at,"#000000", id])
        #now we process the id, this is so we can do a refresh with just the posts since the latest one we have
        #if we haven't stored the most recent id then store this one
        if self.last_id == None:
            self.last_id=id
        else:
            #if we have an id stored, check if this one is 'newer' if so then store it
            if long(self.last_id) < long(id):
                self.last_id=id

    def newTweet(self, widget, text_widget,*args):
        #The other main need of a twitter client
        #the ability to post an update
        #get the tweet text from the input box
        tweet = text_widget.get_text()
        #see if we have just an empty string (eg eroneous button press)
        if (tweet == ""):
            return

        #we get the text in the input box then we construct the outbound tweet
        #first we need to encode for utf-8
        tweet = unicode(tweet).encode('utf-8')
        #then we need to urlencode so that we can use twitter chars like @ without
        #causing problems
        post = urllib.urlencode({ 'status' : tweet })

        #build the request with the url and our post data
        req = urllib2.Request('http://twitter.com/statuses/update.json', post)
        #setup the auth stuff
        auth_handler = urllib2.HTTPBasicAuthHandler()
        auth_handler.add_password(realm='Twitter API',
                              uri='http://twitter.com/statuses/update.json',
                              user=self.username,
                              passwd=self.password)
        opener = urllib2.build_opener(auth_handler)
        # ...and install it globally so it can be used with urlopen.
        urllib2.install_opener(opener)
        json = urllib2.urlopen(req)
        data = simplejson.loads(json.read())
        #message sent, I'm assuming a failure to send would not continue
        #in this method? so it's safe to remove the tweet line
        # what I don't want is to lose the tweet I typed if we didn't
        # sucessfully send it to twitter. that would be annoying (I'm looking
        # at you Mauku)
        text_widget.set_text("");

    def on_window_state_change(self, widget, event, *args):
        #this just sets a flag to keep track of what state we're in
       if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
            self.window_in_fullscreen = True
       else:
            self.window_in_fullscreen = False 

    def on_key_press(self, widget, event, *args):
        #this picks up the press of the full screen key and toggles
        #from one mode to the other
       if event.keyval == gtk.keysyms.F6:
             # The "Full screen" hardware key has been pressed
             if self.window_in_fullscreen:
                 self.window.unfullscreen ()
                 #when we toggle off fullscreen set the cell render wrap
                 #to 500
                 self.cell.set_property('wrap-width', 500)
             else:
                self.window.fullscreen ()
                #when we toggle into fullscreen set the cell render wrap
                #wider
                self.cell.set_property('wrap-width', 630)

if __name__ == "__main__":
    #this is just what initialises the app and calls run
    app = Witter()
    app.run()

And that’s it. I used esbox to develop and just had it using SCP/SSH to copy accross to my n810 and execute directly there, which was a pretty easy way to develop.

There are lots of things I will now go on to add to this client. Things like checking for replies/DMs. Being able to make easy reference to an URLs in tweets, and reply to people etc etc. But I wanted to show the code of the bare bones working in case it helped anyone else get started with developing apps for Maemo.

Developing applications for Maemo

When I first got my nokia 770 I intended to develop for it. I had a few ideas of what to write, but discovered apps already existing for just about everything I could think of. I also discovered that it’s not that easy developing for maemo. To write in C you need scratchbox and an emulated environment. It all looked very complicated and I never got into it.
When I got my n810 I figured it would be fun to try and write an app that could render openstreetmap data, as an alternative to maemo mapper which uses pre-rendered tiles. But again I found Navit, already very good.
I thought about getting involved with Navit development. But I have no C experience and the code is somewhat light on comments.

Recently I decided to have a go again. This time I chose to ignore existing apps. The point is to learn, so I have decided to work on my own twitter client. Yes very trendy…there are hundreds around, but only one really for Maemo, which is mauku.
Part of my reason for chosing to write a twitter client is that it’s pretty simple but covers some basics that will be helpful.
Writing a GUI app that displays data and can scroll
calling out to some webservice and processing the response

I figure if I can get those two then I’ll have a good grounding for lots of projects.

The other part of my reason is that mauku has some very annoying ‘features’ which are driving me crazy. Now I could just raise feature requests and bug reports etc. But again, the point is to learn, so I have to start somewhere. At least this way I don’t feel it’s a complete duplicated effort, I will scratch my personal itch and make a twitter client the way I want it.

I started off trying to write a c application. I found esbox which makes the whole developing with scratchbox thing a much nicer prospect than plain text editors. Being an eclipse tool, I feel right at home using it.

I got my C application as far as being able to display a window, with a menu. And in the menu was a fetch tweets option. When selected it would talk to twitter and fetch my friends timeline into memory, then parse each tweet into a simple structure of name:tweet. Which was then inserted into a list in the display. Hurrah.

However C is a horrible language to work in. I just don’t have time to learn memory management etc. I know I should, I know that the potential is to write a much faster application in C. But I got sick of segfaults. I have no idea how to debug C. I am truly a Java boy. Give me stack traces! Trying to debug why my C code would just randomly explode was impossible (for me) It seemed like sometimes something in the reponse from twitter would cause it to segfault. But more likely I was just memory management completely wrong and was just lucky that occassionally it didn’t explode in my face.

So I’ve decided life is too short for C. Instead I’ve moved on to python. I’ve never written any python before, but it at least saves me from managing memory, and it looks like it’s going to be much closer to things I do know, such as perl.

Python can still be developed in ESBOX with pluthon plugin. This basically lets me write an app then use SSH to dispatch it direct to my n810 to run. So I no longer test in a fake environment. It is probably much slower working this way, but the benefit is that I really know that the app runs on the device. Where as I think I’d always have a nagging fear with running in scratchbox that I might hit some difference in how I had it setup to the real device.

So I started my application again. I’ve been able to reuse at least some of what I had learned about GTK development. This is still the area that I know the least about. It took me ages to get to the point I had the ability to display items on the screen, in a TreeView pulling data from a ListStore. Figuring out how to use items that could be added to by triggered methods and generally getting my head around the scope of objects etc.

Having gotten some basic information appearing on the screen, it then took about 30mins to pick uip the liburl2 library and use it to call twitter to get my status feed.

Now I just need to write some code to parse it into some sensible structure and dislpay. I would point out that I have found that someone has already created a twitter API for python which I could just pick up. I’m sure it does way more, way better than my code will. However, I have to remind myself that the point of this exersise is for me to learn, not just for me to glue other peoples code together.
Also I may not bother with a lot of the things I could process from twitter, Instead just writing a fairly minimal application. At least to start with.

First impression of python is that it’s pretty weird the way it uses indentation to imply structure. If you get the indents wrong then the code won’t work. It feels like it was done by someone who got very upset about people having badly formatted code, so decided to invent a language in which the formatting is enforced because that’s the only way the language will work. Not that I have anything against nicely formatted code. But I’d just as soon have an editor do nice formatting for me to suit my preferences.

Once I feel I know what I’m doing a bit more, I shall write up a post with code fragments to explain what I’ve learned. I think if I put up the code I have right now it would just be confusing. I always find that my initial attempts to get something working are very badly commented and horribly structured. At the moment I’m just throwing stuff in based on API doc and examples and I’m not sure I understand the implications of everything yet. Once I understand it, I can comment it and make it presentable.

I’m hoping that given enough time I’ll understand what I’m doing enough that I can start turning out interesting little tools and hacks. And perhaps finally realise my original intention with my internet tablet to do some mobile development.

First steps in a new software project

This week I started a brand new project. This time it’s the start of product development, rather than just an internal project to get something running. And it really is new, so everyone is new and we’re setting up everything from scratch.

So this is my list of things to go from nothing to a fully fledged software engineering project.

Step one, getting the right tools installed for everyone off the bat makes things easier later on. Standardise upfront rather than try to merge half a dozen separate ideas about whats best later.
For this team we will be testing a GUI so Rational Functional Tester (RFT) with Rational Team Concert (RTC) is the basic tool set.

This gives us all the project management tools in RTC, plus source control, and easy collaboration. Then when we get as far as something to test RFT will already be there.

RTC is the best tool I’ve used for starting projects, it lets you start capturing requirements and high level ’stories’ and start hanging individual tasks off of them. Code sharing is very easy, and delivering code changes under tasks makes the project tracking pretty seamless.

Step two, a build server. It’s easy to link into RTC to have a build engine that allows you to schedule builds as frequently as you like. It also allows people to kick off builds of the mainline code plus their ‘local’ changes. So you can build and unit test changes before delivering them to the main codebase. The outline of this can be set up quickly, the detail of full build and kicking off unit tests takes longer but is a top priority.

Step three is a Rational Quality Manager (RQM) server. This can be linked to the RTC server so that it gets notified when builds complete and also allows you to create defects in RTC if tests fail. RTC can then view defects which block test cases. RQM lets you define what environments you will test in, how you will split things into test plans. And makes it easy to start defining test cases and where they will run. Ultimately it can be used to report on test status, with built in dashboards and report generation.

The last step are some test servers which run adapters which connect to the RQM server. For our needs some of these will use a command line adapter, others will use RFT. This allows RQM to kick off tests against the systems and gather the results.

As a set of tools they are not light weight. Requiring at least 4 servers (RTC, RQM, build, test) but then they are a very powerful combination. I don’t expect to have any spreadsheets or hand-crafted chart generation being done by the team. All of the information we require comes straight from the tools, when we report project status we will use the tools not hand-made slides or spreadsheets. I also expect to be able to get tests automated and managed from the start. So no trying to retro-fit automation onto manual tests.

After one week we have RTC setup with the first wave of requirements stories and tasks, and a code base setup with components for our new product. We have an RQM connected and being told about builds. We have the skeleton of a build system. It’s not doing much other than defining the build types we will have, but the framework is in place.

Next week I’ll setup my first test server. Hopefully in a very short space of time we will have everything we need to develop and test a product. Complete with project tracking and reporting, all while most of the team are focussed on what we will produce, not tied up with figuring out infastructure.

Next Page »


RSS Navit SVN Feed

  • Revision 2820 by martin-s - Fix:Core:Reduced verbosity December 2, 2009
  • Revision 2819 by martin-s - Add:Core:Possibility to activate routing per map independent of rendering December 2, 2009
  • Revision 2818 by martin-s - Add:Core:New vehicle type gpsd_dbus December 1, 2009
  • Revision 2817 by martin-s - Fix:graphics_win32:Correct colors for pngs|Thanks mis December 1, 2009
  • Revision 2816 by martin-s - Fix:Build:Typo December 1, 2009
  • Revision 2815 by martin-s - Add:gui_internal:Possibility to emit a signal when POI is clicked December 1, 2009
  • Revision 2814 by martin-s - Fix:binding_dbus:Wrong callback usage December 1, 2009
  • Revision 2813 by martin-s - Add:gui_internal:Possibility to select bookmark by name November 30, 2009
  • Revision 2812 by martin-s - Fix:Android:Correct surface handling November 29, 2009
  • Revision 2811 by martin-s - Fix:gui_internal:Better anchor handling November 29, 2009

My Twitter

Error: Please make sure the Twitter account is public.

blog Archieve

 

December 2009
M T W T F S S
« Nov    
 123456
78910111213
14151617181920
21222324252627
28293031