Thoughts of the inarticulate.
My thoughts, which I'm no good at articulating.

Thursday, November 20, 2008

Matching HTML tags with VIM

If you have to work with HTML at all, the must-have VIM plugin is Matchit.

Trying to find matching tags in HTML (or often more importantly, missing tags) has always been a head-ache for me and one of the least enjoyable aspect of working with HTML.

Too often has it occurred that I go make some "simple" change to an HTML page, and to my horror when I review my work all of the sudden my once side-by-side columns have become one column on top of another. I know then I'm in for a painful game of tag matching.

With VIM and matchit though, the game isn't anywhere near as painful. Get into it.

Labels: ,

Wednesday, November 12, 2008

The Law of Demeter

The Law of Demeter is something I wish I had learnt early on in my development career. Why isn't at least a whole lecture on this in university? Perhaps there is now.

The best thing about the Law of Demeter is it is short and succinct making it easy to remember:
More formally, the Law of Demeter for functions requires that a method M of an object O may only invoke the methods of the following kinds of objects:
O itself
M's parameters
any objects created/instantiated within M
O's direct component objects

There are just some straight-forward rules for developers to follow to keep their software free of unnecessary dependencies and loosely coupled. People often talk about the need to be loosely coupled and to cut down on dependencies, but I just love how the Law of Demeter just lays it down on how exactly that should be done.

Code that doesn't follow the Law of Demeter can quickly bring the development of that software to a slow crawl. The worst situation you can get into when developing software is when everyone is too scared to touch it. Once you are there, the software has hit its peak. Following Law of Demeter (along with unit testing! get into it!) will keep that software moving along like a smooth well-oiled engine or an agile and nimble ninja. And we all love ninjas.

I first learnt this only about 6 months ago in The Pragmatic Programmer: From Journeyman to Master which is a fantastic book all software developers should read. I can't recommend it highly enough.

I guess it was the sort of practice I already knew and was following where possible, but it was good to see it so clearly presented. Great for passing that knowledge onto others as I sometimes struggle to articulate such things.

Labels:

VIM, Python and indentation

So, I enjoy the Python language.  It seems efficient with CPU and memory, comes out of the box with a large amount of libraries, has a lot of support and some high quality web frameworks (such as Django).

Of course, one cannot mention Python without mentioning indentation.  Initially it was one of the things that drew me to Python, as I liked the idea of consistent indenting producing more readable code across the board.  After plenty of experience with not so readable code with crazy source code formatting (please don't put your body of an if on the same line as the if! :P) this appealled to me.

However, it has taken some getting use to, and early on almost made me give Python away.  And some issues still mean I'm not 100% convinced, but I'm still enjoying using Python and will continue to use it.

So, just some things you should learn if you are new to Python and don't want to pull your hair out using it and its strict indentation:
  1. First, if you are using VIM, download this indent plugin for python.  The default is awful.
  2. How to show whitespace in your editor to find where indentation might have gone wrong (Python will tell you about it).  A common example is a tab mixed in with spaces.  In VIM this is accomplished with ":set list" (and :set nolist to turn off again).
  3. How to indent and unindent the current line.  In insert mode in VIM, the default is C-D to unindent, C-T to indent.  These are a must and save muchos time!!! In normal mode it is "<<" and ">>".
  4. Do NOT reindent big chunks of code unless you know what you are doing (e.g. in VIM using "=" on selections).  With Python you really shouldn't need to, since indentation actually affects how your program runs.
  5. Be careful even reindenting single lines automatically (using "=" in VIM for example).
This brings me to the point that I'm trying hard to get over.  I'm use to being able to select a whole file (of PHP for example) and getting VIM to reindent for me.  Or using a source code formatter to reformat the file.  Now, with Python this isn't necessary, considering file will always be properly indented.  I've have done it out of a reflex action, and the consequences weren't fun.  Just don't do this :)

However, if you in the middle of making some changes (e.g. removing a level of indentation) sometimes you do want to reindent a chunk of code.  Unfortunately, there just isn't enough information in the source code for an automatic reindenting algorithm to know how to correctly reindent.  Without being careful, this can cause significant changes (most likely errors) in your program.

e.g.


1 if foo == bar:
2 print "foo equals bar"
3 if foo == zoo:
4 print "foo also equals zoo"
5 print "end of foo equals bar test"

If you use "=" in VIM on line 5 it will reindent it to the same level as line 4. Obviously this is an error.  I guess this is VIM reindent being too aggressive, but the point is such a subtle change can cause drastic changes in a programs execution.  Imagine a much more complicated example than above with more code at each indent level and (heaven forbid) more levels of indentation.

The fact that a developer NEEDS to be so careful about such a subtle thing with major consequences if they aren't, makes me wonder if Pythons handling of indentation blocks is really the best way to go about it.  Bad indentation in other languages makes it look like a mess, but still work.  Bad indentation in Python still looks ok, but won't work as expected.

That said, what it does encourage is less levels of indentation, and less code per indentation, which is what we should be all doing anyway.  

So to continue on, on how best to manage it, which are useful tips for all languages:
  1. Keep levels of indentation within a function to a minimum (I think keeping to 2 or below should be easy enough)
  2. Keep lines of code per indentation to a minimum.  This raises an interesting question about how many lines of code this should be.  I would say under 10 is ideal, 10 - 20 acceptable, and getting more than that means perhaps you need more functions.  I'm certainly guilty of that, however thinking of my nicest, easiest to work with code, under 20 lines seems like a good number to aim for (this is why squiggly brackets on a new line is the way to go people! Stop complaining about your wasted space and write concise functions! :P)
  3. Be very very careful when reindenting existing code.
  4. Write unit tests! They'll pick up any fuck ups. :)

Labels: , , ,