Posts by Toby

Prototype Inheritence in Python

One of Toby's favorite pastimes is to take concepts from one language and realize it in another. In this episode: Toby implements Javascript-style prototype inheritence in Python.

One thing that is super cool about Javascript is the fact that objects are just maps. Not only can you add attributes dynamically at any point, you can also add methods dynamically. In Python, you can add methods dynamically, but normally you'd have to add it into the class. But there are cases when you don't want to bother making a class. This inspired me to see how far I can go in making Python behave more like Javascript.

Introducing prototype.py

prototype.py lets you write code in Python with Javascript-style prototype inheritence semantics. If you are not familiar with prototype inheritence, just read on for now. I will link to some resources at the end. Now, let's see how to use this bad boy. First you import the module:
>>> from prototype import *
To create a constructor(we don't really have classes anymore), you write a function with the @constructor decorator:
>>> @constructor
... def Person(this, first, last):
...   this.firstName = first
...   this.lastName = last
...
>>> Person
<constructor 'Person'>
I am going to use this rather than self and camelCase rather than under_scores for prototype-style code, because, well...Dorothy, we are not in Kansas anymore.

Now you can do:
>>> bird = Person('Charlie', 'Parker')
>>> bird.firstName
'Charlie'
>>> bird.lastName
'Parker'
You can add attributes to the object just like in normal Python. But unlike in normal Python, which would raise an AttributeError when trying to access non-existent attributes, in prototype-land it merely returns None:
>>> print bird.age
None
You can dynamically add a method to the instance just by tagging on a function:
>>> def sing(this):
...   print '%s sings!!' % this.lastName
...
>>> bird.sing = sing
>>> bird.sing()
Parker sings!!
This affects only the bird instance. If you want the method to be added to all instances of Person however, you can add it to the prototype of Person.
>>> Person.prototype.sing = sing
>>> monk = Person('Thelonious', 'Monk')
>>> monk.sing()
Monk sings!!
This works because Person.prototype is the prototype of the monk instance. In code, this means:
>>> monk.__proto__ == Person.prototype
True
When the sing attribute is not found on the monk instance itself, it will follow the __proto__ reference and look it up in its prototype, which is also referred to as its parent. We can manipulate the parent link:
>>> monkJr = Person('T.S.', 'Monk')
>>> monkJr.__proto__ = monk
so that now monkJr inherits all of monk's attributes:
>>> monk.hair = 'black and curly'
>>> monkJr.hair
'black and curly'
The following are some other properties demonstrating the prototype inheritence model:
>>> assert monkJr.constructor == monk.constructor == Person
>>> assert Object.prototype.constructor == Object
>>> assert Person.prototype.constructor == Person
>>> assert Person.prototype.__proto__ == Object.prototype
If this seems confusing, remember that in prototype-land, there are two kinds of things: constructors and instances. The prototype of a constructor is nothing more than an instance of the type that the constructor represents. A new instance returned from calling a constructor will have its parent set to the prototype of the constructor.

Things You Can't Do in Javascript, i.e. the 1+1>2 Effect

Python is a more powerful and flexible language than Javascript, so, why am I dumbbing it down to Javascript's level? To show that I am not trying to do that at all, let me point out that there are at least a couple of really cool things you can do with prototype.py that you can't with Javascript, simply due to the fact that it is in Python.

The first thing is properties. With prototype.py, you can add properties to objects like so:
>>> def getName(this):
...   return '%s %s' % (this.firstName, this.lastName)
...
>>> Person.prototype.name = property(getName)
>>> bird.name
'Charlie Parker'
You can also specify setters and deleters in the way you'd expect:
>>> def setName(this, name):
...   first, last = name.split(' ')
...   this.firstName = first
...   this.lastName = last
...
>>> def deleteName(this):
...   del this.firstName
...   del this.lastName
...
>>> Person.prototype.name = property(getName, setName, deleteName)
>>> bird.name = 'Dizzy Gillespie'
>>> bird.name
'Dizzy Gillespie'
>>> del bird.name
>>> bird.name
'None None'

The second thing is named parameters, keyword parameters and optional parameters. Let's just do an example with keyword parameters. Let's say I just wanted a way to easily create ad-hoc objects as key-value pairs, I could write:
>>> @constructor
... def Data(this, **kwargs):
...   for key in kwargs.keys():
...     setattr(this, key, kwargs[key])
...
Which lets me write:
>>> project = Data(project='prototype.py', language='python')
But, I could also define methods and properties in this way:
>>> file = Data(fileName='prototype.py', fileExt=property(getExt)
                    read=read, write=write)
Sweet!

A Note About the Implementation

The implementation of prototype.py is only about 60 lines of Python at time of writing, would have gone down to 40 without property support. The code can be found here. 

A big discovery that enabled me to do this was the new module. It allowed me to take a function and make it into an instance method by binding it to an object:
method = new.instancemethod(function, object)

Another note is that I made the design decision that for methods, I chose to store the unbound function rather than the bound method in the __dict__ of the object. I would then bind the function on the fly when it's asked for. This made it very easily to inherit methods because you don't have to worry that the method is really bound to the parent rather than the instance in question.

Further Reading About Prototype Inheritence

If you want to learn more about prototype inheritence, try:
Posted by Toby about 1 year ago about javascript, programming, prototype and python (4 comments)

Null in 10 Languages

  • Java, Javascript, C#: null
  • Ruby, Smalltalk, Lisp, OCaml: nil
  • Lisp: ()
  • Python: None
  • Haskell: Nothing
  • C: 0
Posted by Toby about 1 year ago about c, c#, haskell, java, javascript, lisp, ocaml, programming, python, ruby and smalltalk (0 comments)

Modifying Core Types in ActionScript 3 Using the Prototype Object

ActionScript 3 has a Javascript lineage. It was essentially a fork of Ecmascript. Plus, the Adobe team has worked hard on making the language a proper superset of the Ecmascript specification. This is why although ActionScript 3 was a major architechtural change from 2, and as a result became much more like Java than Javascript, it still has support for the prototype object

When I learned about the prototype object, it was a fresh air from traditional class-based OOP. Studying cool libraries like prototype.js made me realize that the prototype model makes javascript far more flexible than some other strictly class-based OO languages.

One of the cool things you can do with the prototype object in javascript is modify the core classes of the language, like Array, String, and Date. You can do this in ActionScript 3 too, for it conforms to Ecmascript 4. For example, let's say you want to write the collect function for arrays a la ruby. You would do:
Array.prototype.collect = function(f){
  var ret = [];
  for each(var it in this) ret.push(f(it));
  return ret;
}
There you see me using the nice  for each syntax. But, this is going to break the behavior of the array, because now the collect function is going to show up in the enumeration in the for each loops. We don't want that, so to fix that we are going to set the collect attribute of Array.prototype to not be enumerable:
Array.prototype.setPropertyIsEnumerable('collect', false);
This allows you to write the following code:
[1,2,3].collect(function(i){ return i * 2; });
// result would be [2,4,6]
It's kinda tedious to have to setPropertyIsEnumerable for every time we add a function to an existing type, so I wrote a convience function:
function addMethodsTo(cls:Class, methods){
    for (var name:String in methods){
        cls.prototype[name] = methods[name];
        cls.prototype.setPropertyIsEnumerable(name, false);
    }
}
Which you can use like so:
addMethodsTo(Array, {
    collect: function(f){
        var ret = [];
        for each(var it in this) ret.push(f(it));
        return ret;
    },
    anotherMethod: function(){
        ...
    },
    ...
});
This is sort of like the style prototype.js uses for extending/creating classes.

A Word of Caution

Before you consider going further with this, I must advice you to think twice before using this technique(however, I hope you do decide to use it afterwards ;). There are several caveats:
  1. The prototype-based style is a second-class citizen in the world of ActionScript 3 and Flex. The Adobe team as well as the community seem to be much more committed to the class-based approach. I will describe some of the rough edges below.
  2. You will give up compile time type checking for the portions of your code that use this style.
  3. Prototype inheritence is handled by a completely different mechanism than class-based inheritence in the Flash VM and is not as performant.

Where to put this Code?

You saw the code example above, but, where do you put it? Since I decided to use a helper function(addMethodsTo), the code cannot be directly pasted inside the class scope of a class unless the addMethodsTo function is declared to be static(you can only make a method call directly inside class scope if it is a class method). As, a general solution, I'd rather the code be portable. So it should be includable in both class and function scope, and also, I'd like it not to pollute any namespaces.

My current solution is to put this bit of code inside an anonymous function which immediately gets executed:
// contents of includes/Array.as
(function(){
    include 'addMethodsTo.as';
    addMethodsTo(Array, {
        collect: function(f){
            var ret = [];
            for each(var it in this) ret.push(f(it));
            return ret;
        }
    });
})();
The addMethodTo function is pulled into a separate file to be easily includable else where.
So, with this, I would do the following to include this Array functionality:
include 'includes/Array.as';
Head over to Github for the complete structure of the files.

These methods are added during runtime - at exactly the time the above line of included code is executed, and not a moment before. I like to do the include at the top level of the application, this way the entire program has immediate access to the new methods. Oh, and when I said entire program, I do mean the entire program - not just the files that happen to include the file. Well, this is good and bad. This means if you create components that use the array extensions you've created without explicitly including it(you've included it at the entry point of your program), then you have created an invisible dependency. If you try to take the component and use it in a different project without the array extensions, it will not work. Of course, you could also make the dependency explicit by including the file everywhere you are using them, but 1) that's kinda tedious/repetitious, and 2) there's nothing enforcing you to do this.

Pitfalls and Gotchas

As I mentioned, the prototype-based programming style is a second-class citizen in the ActionScript 3 world, and so, its use is not particularly well supported. First of all, the compiler does not recognize any of the methods added via the prototype mechanism, and thus cannot perform static type checking on them. But what is funny is the way the compiler copes with this - it depends...on the type in question. For Arrays, the compiler simply allows all method calls - you can call any method on an array, even if it doesn't exist, the compiler won't complain. So, for a call like:
[1, 2, 3].collect(...);
The compiler won't even say a word. But for Dates, it gives a warning message. This:
new Date().format()
would trigger this warning:
Warning: format is not a recognized method of the dynamic class Date.
But, for strings, it's a different story still:
'one, two, three'.csv2Array()
compiler says:
Error: Call to a possibly undefined method csv2Array through a 
    reference with static type String.
And the same thing with numbers:
(2).minutes().ago()
compiler says:
Error: Call to a possibly undefined method minutes through a 
    reference with static type int.
The work around for strings and numbers is to upcast it to an Object:
Object('one, two, three').csv2Array();
Object(2).minutes().ago();
or if you just have an untyped variable, it'll work just fine:
var x = 2;
x.minutes().ago();
See the full code example here, and the demo here.

What about runtime error handling? So let's see what happens if you don't include the extensions and run the code. When I took out the array extension methods, the runtime dutifully throw me the:
TypeError: Error #1006: collect is not a function.
This is good, just what I would expect. For Date, it works the same way. Now let's try taking out the string extensions:
TypeError: Error #1006: value is not a function.
Uhh, what? Not really sure what you mean. And as you would expect, it works like this for Number as well.

I have also seen cases where the runtime simply completely muffles an error when there's an undefined method being tried as someone documented here. But I am not able to reproduce this just now. Also on another note, the error stacktrace from the flash player(debug version) is not very helpful because although it gives the call stack, there are no line numbers. I am sure that you'd get a better experience using Flex Builder, however.

I think that about wraps it up. Although extending core types is fun, powerful, and elegent, it's also full of holes and flying scissors everywhere. Are you ready to jump into this brave new world?

A message to the Adobe Flex/ActionScript team: I implore you to put more effort into the prototype-based side of the language. It allows for many possibilities which its class-based counterpart cannot offer. I don't dislike the class-based approach. I think the two each have their own strengths and weakness. Which is why I love this hybrid aspect of ActionScript 3 which allows me to use either style in the same environment. I believe that if the prototype-based aspect of ActionScript were to improve and get more exposure, it would not only become a better language, but also a more wide spread language.
Posted by Toby about 1 year ago about actionscript, flex, javascript, programming and prototype (11 comments)

ActiveRecord Gotcha

I came across this interesting gotcha while debugging through someone else's rails code. When you set a model's one-to-many attribute(an perhaps other association types as well), let's say:
user.friends = new_friend_list
It doesn't always set it. As far as I can figure from my blackbox testing, it does an equal check first between the old value and the new value, and then sets only if they are different.

Now, in Ruby's == is easily overridable, you can easily make it do anything you want. It happens that Array#== returns true iff both arrays have the same number of elements and each element in one array is == to the element of the other array in the same position. It also happens that ActiveRecord's base class' == returns true as long as the objects are of the same class and the primary keys equal.

Which brings us to the gotcha of the day. The code in question built an array, say new_friend_list independently, starting with an id list passed in from a from, finding each friend in the database and adding them to the array, but, in the meantime, modifying a field in each of the friends, say...friend.charma++. It then goes on to set the friends attribute in the manner you'd already seen above, and saves user. Well, the charma field that was modified in each of the friends retrieved did not get saved, because the set did not happen: the new_friend_list pointed to the same list of friends user was already associated to.

Hmm..., yeah. Watch out for this one. Debugging this one was not fun. It definitely didn't fit with the principle of least surprise.
Posted by Toby about 1 year ago about gotcha, programming, rails and ruby (0 comments)

Start Pidgin on Windows Startup

This took me forever to figure out how to do, even when I'd figured it out some time before, so I thought I'd better document it here.

To get Pidgin to start on startup on Windows, go to Tools -> Plugins (yeah, that's right, it's a plugin). Find Windows Pidgin Options in the list, check it off, and click the Configure Plugin button. Now you should see the Start Pidgin on Windows Startup option.
Posted by Toby about 1 year ago about pidgin, tech and windows (0 comments)

Using the Flex-Ajax Bridge

The Flex-Ajax Bridge is a little javascript library bundled with the Flex SDK that allows you to use javascript to drive your Flex app. It can be really handy for debugging or experimentation when you use it with Firebug's console. For complete setup up instructions, see here. You do need to modify your Flex code to get the bridge to work. It's just a one-liner though.

To use it, first you get a reference to your flex app:
app = FABridge.flash.root()
To get a component by ID, you would do something like:
app.get('myDataGrid')
To find out the type of the component:
app.get('myDataGrid').typeName
You can call the methods of the component as you would in normal ActionScript. To access the component's properties though, you need to use the Java getter/setter convention:
app.get('myDataGrid').getSelectedItems()
This isn't so nice. Ideally, a seamless experience would allow you to write:
app.myDataGrid.selectedItems
I guess this is where the weakness of Javascript is coming through. There's no language support for properties(like those in ActionScript, C# Python, etc.) and also no way to do method interception(method_missing in ruby). But I digress.
To instantiate an object of a class in Flex-land, you'd do something like:
sprite = FABridge.example.create("flash.display.Sprite");
This would call the default constructor. I am not sure how you'd call a constructor with arguments, probably just add on the arguments to create()?
A really cool and useful thing you can do is pass functions as event handlers to into Flex-land. Try this:
app.get('myButton').addEventListener('click', function(e){
    console.log('button clicked!');
});
Now go click that button...cool, heh?

Anyway...in conclusion, the Flex-Ajax Bridge is really nice...especially when combined with Firebug.
Posted by Toby about 1 year ago about firebug, flex, javascript and programming (0 comments)

Different Ways of Including Functions in ActionScript

This is another example of something that would have been a blog post creeping over to SO.
Posted by Toby about 1 year ago about actionscript, flex and programming (0 comments)

Notable blogs I read

Posted by Toby about 1 year ago about blogs, tech and web (0 comments)

Redirect 301

I was looking at Google Analytics today and found that I was getting a bunch of traffic on Use Delicious with Chrome as well as some programming/technical articles, but on the wiki.futuretoby.com domain rather than on the tobyho.com domain. 

For those of you who don't know(probably all of you, because...why would you?), this "wiki/blog" runs the on 2 separate domains, but with a different facade over each one, if you will. One is for my family/personal stuff, for which most of the content it is intended for has access restrictions. The other is the tobyho.com domain, which I created more recently and is mainly for my public content. But all of the content can be accessed in exactly the same way on either domain.

So, basically, the former domain is still more visible on the Google search engine than the latter, and so people are coming to my articles on that one, rather than where I want them to go: tobyho.com. 

How to fix it? Well, it turns out that for things like this, a 301 redirect(as supposed to a 302) is the way to go. It will tell the search engine that the content has moved permantly, and so prompt it to update its index. The code I ended up putting together was pretty simple:
    tag_names = @page.tag_names
    if request.host != 'tobyho.com' and
        @page.authors.include?(toby) and 
        not tag_names.include?('family') and 
        (tag_names.include?('programming') or 
         tag_names.include?('tech') or 
         tag_names.include?('gadgets')) then
        headers["Status"] = "301 Moved Permanently"
        redirect_to("http://tobyho.com/#{@page.title_for_link}", :status => 301)
        return
    end
So, basically, if a visitor comes to an article from the other domain, I want to redirect to the tobyho.com domain if 1) I am the author, 2) the article is tagged with one of programming, tech, and gadgets and 3) the article is not tagged with family. The line:
headers["Status"] = "301 Moved Permanently"  
Is not needed if you're on a newer version of rails, for which setting :status => 301 on the next line would suffice. I embarrassed to say that I am still on 1.2.x.
Posted by Toby about 1 year ago about programming, rails and web (0 comments)

Dabbling in Dabble

I'd been really impressed with Dabbledb just from seeing the video demo. I eventually decided to try using it to organize my music collection. I am mostly a jazz listener when it comes to music, and I have had this idea of building an extended jazz catalog for a while now - just in my back burner. So the idea was to see if Dabble is a good fit for this project.

Dabble is really awesome, and one of the really awesome things about it is the import.

Me: You know how I imported my iTunes library into dabble?
You: Um, probably parsed the itunes library xml file, and converted it to a format dabble takes - maybe a rest service of some sort...
Me: Wrong! I opened up itunes, pressed Ctrl-A to select all files in my library, Ctrl-C to copy, then Ctrl-V to paste into the import textarea of Dabble, click "Import", and BAM!

Well, okay, in reality there's a bit more to it. In iTunes, you want to add all the columns you want to export into the display. This is easy: just right-click on the column header and it will should you all the available fields and which ones are currently displayed. Check and uncheck as you see fit. Now, after the copy-and-past and a clicking Import inside Dabble, it should parse the tab delimited text correctly, and present you with a table view of the fields and a few rows of the data that it got. You can now tweak the field types before you finally do the final import.

Now, the next great feature of Dabble - in my opinion the greatest - is that you can just refactor the schema as you go. iTunes gives you a flat list of tracks - the artist and album fields for example, are just string fields. The obvious next step for me is convert these to related models, so that I can add additional information to the artists and albums and so that I can navigate my catalogue by album or artist, etc. In Dabble, this is dead simple. It's a one step process, you convert the string field into a link to a related category(your model, or entity in O/R speak), you can create the new category, say Album on the fly. The process will iterate over all the values of the field, group the common ones, and create an entry in the new category for each unique value. This feature, plus others which I will mention, means that your data model in Dabble are extremely malleable, which is not like the rigid O/R databases you are used to at all. I started out with one model: Track, and have since been refactoring it incrementally into more and more models. At this point I have 8 models: Album, Artist, Company, Instrument, Organization, Personnel, Song, and Track. Some of these models required additional data from other sources, but most were taken straight from the iTunes export. I must mention also, that changing your data model with actual data is very different from just drawing boxes and lines. Because the data is so concrete - ex: Bill Evans(Piano), My Foolish Heart - you see a realistic view of how well your data model fits with the actual data. I think it's a better data modelling tool than your standard O/R diagramming tools, of course, provided that you have actual data to work with.

Dabble has a one level undo for all operations. You can still screw up though if you go on to something else before you realize you need to undo - I already did this once. If you screw up, you can restore to a previous snapshot of your db. Dabble automatically snapshots your data about 5 times a day. You can also manually tell it to take the snapshot in the admin page. The restore process is just 2 clicks.

Also, you can change the field type of a column very painlessly. You just select configure -> change field type -> select the type you want -> done. It will convert the data for you semi-intelligently. For most cases this works okay. If not you can always undo or revert to your previous type. But I wish the data conversion was a little bit more configurable. For example, Dabble looked at the duration field of the track - for which the values looked like 6:23 - and assigned it the Duration type by default. This is exactly correct excepted that it interpreted 6:23 as 6 hours and 23 minutes. Another issue I had was the track number field. iTunes outputs the track number in the format 1 of 7, for example. I would like to convert this to just a number, getting rid of the of 7 part, and making it a Number field. Currently, there aren't sufficient options in the type dialogs for me to do that.

The UI is very well done. It's intuitive, all the possible actions are close by and just 1 or 2 clicks away. Search/filtering works nice. Mass edit is a useful feature. I especially like the merge feature, which I use a lot to clean up duplicate data. I like how one-to-many and many-to-many associations are displayed comma separated by default. You can customize almost everything about the views. There is still room for improvement, however. It is still quite tedious to enter large amounts of data, especially when there are many related models. I think they could make use of Ajax a bit more to reduce the number of full page loads. If it were me, I would make the core of the app(where you view, search, configure fields and edit data) a one page app.

Overall, I am loving Dabble. Avi Bryant is my hero. I'm going to be working on the music catalogue for a while, and I definitely see myself using this for other projects in the future.
Posted by Toby about 1 year ago about dabble, database and tech (0 comments)

A Custom Drag-n-Drop List Control

The List control supports drag-n-drop support out of the box - just not the way I want. What it does is allow you to drag something from another list or other type control and drop onto it there by transfering the object dragged into the list control itself. What I want is for something to be dropped onto an item in the list in question. This is how I ended up doing that.

By looking at the implementation of ListBase.as in the flex framework source code, I found that I needed to override some methods. So I create a MyList.as file which subclasses the List control. The methods I first needed to override were dragEnterHandler and dragOverHandler. Both of these methods in ListBase.as look almost identical, here is the source for dragOverHandler:
    protected function dragEnterHandler(event:DragEvent):void
    {
        if (event.isDefaultPrevented())
            return;

        lastDragEvent = event;

        if (enabled && iteratorValid && event.dragSource.hasFormat("items"))
        {
            DragManager.acceptDragDrop(this);
            DragManager.showFeedback(event.ctrlKey ? DragManager.COPY : 
		DragManager.MOVE);
            showDropFeedback(event);
            return;
        }

        hideDropFeedback(event);
        
        DragManager.showFeedback(DragManager.NONE);
    }
The showDropFeedback method draws a line in the List control that indicates where the new item would be inserted into the List. This doesn't apply to us anymore, so I overrode the showDropFeedback method, to just highlight the item under the cursor instead:
        override public function showDropFeedback(event:DragEvent):void{
            var item = findItemForDragEvent(event);
            var uid:String = itemToUID(item.data);
            if (item){
                drawItem(item, isItemSelected(item.data), true, 
			uid == caretUID);
            }
        }
Moreover, now we want to accept the drop only if the cursor is over a list item, whereas before it allowed for drops on empty parts of the List area. This what I did:
        override protected function dragEnterHandler(event:DragEvent):void{
            _dragOverHandler(event);
        }
        
        override protected function dragOverHandler(event:DragEvent):void{
            _dragOverHandler(event);
        }
        
        public function findItemForDragEvent(event:DragEvent):Object{
            var item;
            var lastItem;
            var pt:Point = new Point(event.localX, event.localY);
            pt = DisplayObject(event.target).localToGlobal(pt);
            pt = listContent.globalToLocal(pt);
            var rc:int = listItems.length;
            for (var i:int = 0; i < rc; i++)
            {
                if (listItems[i][0])
                    lastItem = listItems[i][0];

                if (rowInfo[i].y <= pt.y && 
			pt.y < rowInfo[i].y + rowInfo[i].height)
                {
                    item = listItems[i][0];
                    break;
                }
            }
            return item;
        }
        
        protected function _dragOverHandler(event:DragEvent):void{
            var item = findItemForDragEvent(event);
            if (item){
                DragManager.acceptDragDrop(this);
                DragManager.showFeedback(
			event.ctrlKey ? DragManager.COPY : 
				DragManager.MOVE);
                showDropFeedback(event);
            }else{
                DragManager.showFeedback(DragManager.NONE);
            }
        }
I wrote a findItemForDragEvent method to find the item that the cursor is currently under or null if none exist - the code was mostly stolen from the calculateDropIndex method in ListBase.as - then I accept the drop if I get a non-null value from it.
I think that's pretty much it. Here's the demo and the code.
Posted by Toby about 1 year ago about dnd, flex and programming (1 comments)

Getting Things Done

I finished my copy of Getting Things Done by David Allen. Given how extremely influential this book was, it was a bit surprising that it wasn't more well written. My main problem with it is that it wasn't organized very well: duplicate information was scattered in different parts of the book - it felt a bit rambling at places. Because of this, I want to write a couple of articles on GTD, summarizing the book.

So..., here I go. This will be the first article of the sort.

I think that the second to last chapter of the book is the best chapter and really summarizes best what GTD is all about. It should probably have been the first chapter. And so, I am going to talk about it first. The three principles of GTD:
  1. The power of capture
  2. The power of the next action decision
  3. The power of outcome focusing


The Power of Capture

GTD is based first on the principle of capturing all your "stuff". Stuff is just anything your mind thinks of that requires your attention - not just limited to just things you have to do. If you put all of you stuff into the physical world, you relieve your mind of the responsibility to remember them, freeing up your phychic RAM, thus you can focus your mind on other things, like executing on the things you need to do and being creative when you are brainingstorming. The state of having your phychic RAM empty is refered to as mind like water, in that you are ready for anything, because you have all of your mind to work with. Using the computer analogy, when you have more RAM, your program just runs much faster. While the human mind is great at recognition, it is not nearly as good as computers in sequential retrieval of memory, i.e. going from top to bottom through a list of stuff. For example, it's very hard to remember a list of unrelated things. This is why it's a good idea to dump your memory into the physical world, by making lists, either on paper or on the computer.

When you capture all aspects of your life, you end up with a hugh repository of stuff. So you'd better have a good system to keep it all organized. GTD provides a system for organizing your stuff which comprises of several lists and a workflow to systematically sort your stuff into these lists. I will go into more details in describing this system in a later article.


The Power of the Next Action Decision

GTD is about directing your energy towards...well, getting things done. For example, the technique of sorting your task by context - or where you are at the moment - is designed to streamline your work. Many of the principles of GTD are rooted in psychology, which I really like about this book. The principle of the next action decision is one such principle. People - especially smart people - tend to procrastinate. This is because we tend to visualize and imagine when ideas are brought to our attention. When a non-trivial project is brought to our attention, chances are we are thinking of all the difficulties involved in finishing the project. This thinking discourages you from the actual doing, because you can not easily visualize the end to the project, nor the reward - the satisfaction of getting it done. If on the other hand, you split out the projects into very small tasks, each individual task becomes readily doable. And so, rather than filling your todo lists with project titles like:
  1. get in shape
  2. fix car
Replace them with the very next action for in the series of actions required to complete the project, like:
  1. research gym memberships in the area on Google
  2. call mechanic to make an appointment
When you look at these next action items, you no longer feel overwhelmed, and you possibly even want to do a task because you can very easily visualize it being done, and getting the satisfaction of having it finished. That's the power of the next action decision, and why you should figure out the next action ahead of time - when you write your list, and not when you are about to do it.


The Power of Outcome Focusing

Third and finally, since GTD allows you to be so efficient at plowing through your tasks, you run the danger of losing focus and wasting your energy on non-essential or even irrelevant tasks. This is prevented by thinking about your goals and envisioning the outcomes you want at multiple perspectives regularly. GTD suggests weekly reviews of all your lists as wells as bigger reviews staged at bigger intervals.

To me, these are the three most important take aways from the GTD book. For the next article, I will describe the system of lists and the workflow as laid out in the book.
Posted by Toby about 1 year ago about books and gtd (0 comments)