31 December 2006

Summary of Bad Code Smells from Refactoring by Martin Fowler

Summary of bad smells from Refactoring by Martin Fowler

Duplicated Code: The same code structure in two or more places is a good sign that the code needs to be refactored: if you need to make a change in one place, you'll probably need to change the other one as well, but you might miss it

Long Method: Long methods should be decomposed for clarity and ease of maintenance

Large Class: Classes that are trying to do too much often have large numbers of instance variables. Sometimes groups of variables can be clumped together. Sometimes they are only used occasionally. Over-large classes can also suffer from code duplication.

Long Parameter List: Long parameter lists are hard to understand. You don't need to pass in everything a method needs, just enough so it can find all it needs.

Divergent Change: Software should be structured for ease of change. If one class is changed in different ways for different reasons, it may be worth splitting the class in two so each one relates to a particular kind of change.

Shotgun Surgery: If a type of program change requires lots of little code changes in various different classes, it may be hard to find all the right places that do need changing. Maybe the p[laces that are affected should all be brought together into one class.

Feature Envy: This is where a method on one class seems more interested in the attributes (usually data) of another class than in its own class. Maybe the method would be happier in the other class.

Data Clumps: Sometimes you see the same bunch of data items together in various places: fields in a couple of classes, parameters to methods, local data. Maybe they should be grouped together into a little class.

Primitive Obsession: Sometimes it's worth turning a primitive data type into a lightweight class to make it clear what it is for and what sort of operations are allowed on it (eg creating a date class rather than using a couple of integers)

Switch Statements: Switch statements tend to cause duplication. You often find similar switch statements scattered through the program in several places. If a new data value is added to the range, you have to check all the various switch statements. Maybe classes and polymorphism would be more appropriate.

Parallel Inheritance Hierarchies: In this case, whenever you make a subclass of one class, you have to make a subclass of another one to match.

Lazy Class: Classes that are not doing much useful work should be eliminated

Speculative Generality: Often methods or classes are designed to do things that in fact are not required. The dead-wood should probably be removed.

Temporary Field: It can be confusing when some of the member variables in a class are only used occasionally

Message Chains: A client asks one object for another object, which is then asked for another object, which is then asked for another, etc. This ties the code to a particular class structure.

Middle Man: Delegation is often useful, but sometimes it can go too far. If a class is acting as a delegate, but is performing no useful extra work, it may be possible to remove it from the hierarchy.

Inappropriate Intimacy: This is where classes seem to spend too much time delving into each other's private parts. Time to throw a bucket of cold water over them!

Alternative classes with different interfaces: Classes that do similar things, but have different names, should be modified to share a common protocol

Incomplete Library Class: It's bad form to modify the code in a library, but sometimes they don't do all they should do

Data Class: Classes that just have data fields, and access methods, but no real behaviour. If the data is public, make it private!

Refused Bequest: If a subclass doesn't want or need all of the behaviour of its base class, maybe the class hierarchy is wrong.

Comments: If the comments are present in the code because the code is bad, improve the code

GoF Patterns

Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides

Creational Patterns How to make an object.
Factory Method Makes an instance of several derived classes based on interfaced data or events.
Abstract Factory Creates an instance of several families of classes without detailing concrete classes.
Builder Separates object construction from its representation, always creates the same type of object.
Prototype A fully initialized instance used for copying or cloning.
Singleton A class with only a single instance with global access points.

Structural Patterns The building blocks of objects
Adapter Match interfaces of different classes therefore classes can work together despite incompatible interfaces
Adapter Match interfaces of different classes therefore classes can work together despite incompatible interfaces
Bridge Separates an object's interface from its implementation so the two can vary independently
Composite A structure of simple and composite objects which makes the total object more than just the sum of its parts.
Decorator Dynamically add alternate processing to objects.
Facade A single class that hides the complexity an entire subsystem.
Flyweight A fine-grained instance used for efficient sharing of information contained elsewhere.
Proxy A place holder object representing the true object

Behavioral Patterns the way objects play and work.
Interpreter A way to include language elements in a program to match the grammer of the intended language.
Create the shell of an algorithm in a method, then defer the exact steps to a subclass.
Chain of
A way of passing a request between a chain of objects to find the object that can handle the request.
Command Encapsulate a command request as an object to enable, logging and/or queuing of requests, and provides error-handling for unhandled requests.
Iterator Sequentially access the elements of a collection without knowing the inner workings of the collection.
Mediator Defines simplified communication between classes to prevent a group of classes from referring explicitly to each other.
Memento Capture an object's internal state to be able to restore it later.
Observer A way of notifying change to a number of classes to ensure consistency between the classes.
State Alter an object's behavior when its state changes
Strategy Encapsulates an algorithm inside a class separating the selection from the implementation
Visitor Adds a new operation to a class without changing the class

27 December 2006

Scrum and XP from the trenches - Henrik Kniberg

Some system development principles

Empathy Box :: 5 Principles For Programming got me thinking, so I put down some principles I go by too...


A classic... minimise coupling (dependencies). E.g. having to remember to call a method before another; having to call many methods to achieve a usecase, gathering some state from earlier method calls to pass into later method calls. Where possible enscapsulate or hide (once called modularity) this complexity in a single class/method which reduces the passing of state from one class to another, i.e. keep the state as close to the behaviour that requires it.

Avoid cyclic dependencies between classes, packages and systems. All dependencies should form a directed acyclic graph. The most stable and generic code should drop to the bottom of the graph and the most volatile code should rise to the top of the graph - refactoring can help push code up or down the dependency graph. Another way of stating this is that if class A depends on class B, then class B should be more stable than class A. Splitting a large application up into multiple modules, that are compiled seperately, helps enforce dependency rules. Classes that don't change together or are not reused together don't belong in the same module.

Under no circumstances allow code duplication, copy and paste is a sin punishable by death. In fact, avoid duplication of all kinds, maximise reuse of code, data, systems...

Avoid static state, pass as many dependencies into a class through the constructor (constructor-based dependency injection). This improves encapsulation and reuse of classes. All dependencies are explicit and the caller can decide the implementation of dependencies to pass into the class (assumming dependencies are expressed as interfaces or abstract classes). Avoid singletons (or static factories that contain state) at the pain of death, when an object uses singletons it becomes difficult to manage the dependencies of that object.

Avoid mutable state where possible strive for immutability. Changing state often leads to more bugs. I often use the final keyword for variables and very occasionaly for parameters too. Also do not add setters just for the hell of it, only add them where they are absolutely essential. I always prefer passing state in through a constructor, rather than through setters, this helps avoid cyclic dependencies between objects as well as avoid mutation.

Be ruthless with refactoring, extract common abstractions whereever you seem them but avoid premature abstraction, only extract abstractions when you have multiple concrete instances that share patterns of structure or behaviour or where you are sure there will be multiple concrete instances at some point. Applies some rules to inheritance based abstraction: "the Liskov Substitution Principle" states derived classes must be usable through the base class interface without the need for the user to know the difference. Ensures details depend upon abstractions and that abstractions do not depend upon details.

Be ruthless with deleting redundant code (you can always retrieve the code from your version control system). The less code there is, the more maintainable the system and the less bugs you have. So remove unused methods, fields, classes, packages etc. Modern IDEs help highlight unused code as do code coverage tools.

Avoid premature optimisation, however dont just write cr*p code either. Balance optimisations against the complexity they add. So if an optimisation doesn't add any complexity it is a no-brainer, just do it in the first place.

Use external libraries where possible rather than reinvent the wheel. Less code means less bugs and easier maintenance. E.g. log4j, ant, hibernate, apache commons-*, spring.


Ensure the team sits together, even better if all stakeholders (e.g. developers and business users) sit together. This allows for adhoc conversations during which knew insights are created and knowledge is shared. It allows for immediate feedback on interpretations of requirements, which ensures developers are always on track, delivering what the business wants. Even a corridor seperating team members will affect the ability of the team to work together.

Focus on recruiting a team of experts who can take the system through all stages of development, i.e. they have the skill to gather requirements, think about architecture, think about design and are responsible for coding, testing, release into production and initial (or second-line) support. Seperating these roles only causes communication problems especially because systems development is an iterative process, i.e. you gather a few requirements, think a little about architecture/design, write some code, realise your design doesn't work, rework it, then find out that some of your requirements are ambiguous and have to delve a little deeper into them. I think its ridiculous to hand over a design to coders and equally for coders to just knock something up and pass the result on to some sort of test team. Seperating roles also allows for "passing the buck" when the project inevitably fails. A small, multi-function team doesn't need to rely on documents (e.g UML-based specifications) they can just talk through important issues, possibly white-boarding them where necesary.

Invest enough time and effort in recruitment. The composition of the team is the most important factor determining the success of the project. Think about succession management, team members will get bored doing what they doing, if they are not given new challenges, or they may just leave for other external factors. So recruit even when you can manage with the current head-count. Its best to have a little spare capacity and have a constant handover (knowledge sharing) than be faced with trying to recruit for and handover a collegues role within a month.


Regular releases of the system.

Don't count the pennies when it comes to buying software development tools, for Java these might include a good ide such as Jetbrains Intellij IDEA, a decent profiler such as YourKit Java Profiler and a sql database tool such as Minq Software's DBVisualizer.

Use non-ide specific build files. I've not tried using a project-model based tool such as Maven or a continuous integration tool such as CruiseControl but I think they are worth considering.

Run unit-tests regularly. I don't really practise test-driven development, but ensure that the tests you do write get executed on more than an adhoc basis.

Once in a while run your system through a profiler to ensure you've not added many more cpu hotspots, increased memory usage or introduced memory leaks. Of course, this doesnt help you find cases where you've increased the cpu usage on a uniform basis across many areas (as they will not be hotspots), so it may be worth writing some some of standard system test that you execute and record timings for. That way a few months down the line, you can reexecute the test and compare timings against previous ones.

26 December 2006

The Elements of Ant Style

Empathy Box :: 5 Principles For Programming

Javolution collections api

I think I will be making more use of javolution.util for high performant code. I do believe that optimising code should be balanced against the code complexity it adds, however if you can make code more performant without adding any complexity or the added complexity is not to great then its a no-brainer.

Some things about the standard collections api bug me, e.g looping collections by creating iterators (especially in code that is called many times); the implementation of equals/hashCode in List implementations which uses an iterator rather than some form of array-based access.

Bhavaya-like products

Gemstone GemFire Real-Time Events see TheServerSide.com Thread
Tangosol Coherence Continuous Query

For those who don't know, one of the aims of Bhavaya is to allow for users to specify the data they want as criteria (which is ultimately translated to sql queries, much like Hibernate), the library will then return a collection of beans matching this criteria and then keep this collection current as data in the database is changed, for example, beans may be inserted, updated or deleted from the collection. The collection fires events to listeners to inform them of changes to its elements. Bhavaya focuses on efficiency, by applying deltas to the collection without hitting the database again, this allows for efficient distributed, observable caches of data.

28 October 2006

converting a wma file to mp3

mplayer -ao pcm:file="dub_be_good_to_me.wav" dub_be_good_to_me.wma

lame -V 2 --vbr-new dub_be_good_to_me.wav -o dub_be_good_to_me.mp3

remember to ensure that mplayer isnt configured for looping in /etc/mplayer/mplayer.conf

06 October 2006

Sending mail with attachments from the command line

echo "The body of the email" | mutt -s "The subject" -a file.txt somebody@somewhere.com

You can use multiple -a flags to and many attachments, mutt checks the file extension to determine the mime type

05 October 2006

Adding an ssh public key to another account

cat .ssh/id_rsa.pub | ssh username@otherhost 'cat >> .ssh/authorized_keys'

24 September 2006

Edit nautilus "open with" right-click actions

Configuration for these actions are stored in /usr/share/applications/mimeinfo.cache, entries in this file link to files in /usr/share/applications/. E.g. /usr/share/applications/redhat-audio-player.desktop contains the command-line options used to start xmms.

Normalising volume of mp3 tracks - Part 2

This script handles albums properly so that the relative volume of seperate tracks in an album are maintained:



cd /srv/files/music

for album in `find . -mindepth 2 -type d -not \( -regex '\./.*/singles$' -or -regex '\./various/.*' \)`; do
echo "Processing album ${album}"
mp3gain -a -k -c ${album}/*.mp3

for singles in `find . -mindepth 2 -type d \( -regex '\./.*/singles$' -or -regex '\./various/.*' \)`; do
echo "Processing singles ${singles}"
mp3gain -r -k -c ${singles}/*.mp3

) | tee /var/log/normalise_music.log

Normalising volume of mp3 tracks

(find /srv/files/music -type f -iname '*.mp3' -print0 | xargs -0 -n 1 mp3gain -r -k -d 2) | tee mp3gain.log

MP3Gain does not decode and re-encode the mp3 to change its volume (this is good). You can change the volume as many times as you want, and the mp3 will sound just as good (or just as bad!) as it did before you started. Mp3Gain uses a special algorithm to calculate how loud the file actually sounds to a human's ears and writes a tag corresponding to the decibel value in the mp3. That tag will be read by any mp3 player that you play the file with. Let Mp3Gain analyze your whole mp3 library and all your songs will sound the same volume! But if for some reason, you want the volume back to its original value, Mp3Gain can remove the tag for you and the volume will be just as before.

You can first remove any existing gain values for music retrieved from unknown source using:

find . -type f -iname '*.mp3' -print0 | xargs -0 mp3gain -u

28 August 2006

Encoding flac files into mp3 files

for i in *.flac; do flac -sdc "$i" | lame -V2 --vbr-new - "${i%.flac}".mp3; done

22 July 2006

A helicopter ride over London

Went on a helicopter ride last weekend, there were some great views. Here are some photos, click on each photo to see it in more detail:

12 July 2006

xargs and find

find /srv/files -name "Thumbs.db*" -print0 | xargs -0 /bin/rm -f {}

This deletes all files matching pattern Thumbs.db*. -print0 and -0 cause delimitation by the null char rather than whitespace, so filenames can contain whitespace.

If you add -i to the xargs options the command will be called once for each entry rather than receiving a list of entries, e.g :

find . -name "${pattern}" -print0 | xargs -0 -i convert -verbose -quality ${compression} {} {}

Note, with -i {} can be repeated multiple times in-place of the entry.

10 July 2006

Favourite Firefox extensions

Adblock Plus
Copy Plain Text
Delicious Bookmarks
Download Statusbar
Febe (I'm still looking for a decent profile sync other than file sync)
Foxmarks Bookmark Synchronizer
IE Tab
Search Marker
Web Developer

Updated (24/06/2008)

09 July 2006

Check disks with e2fsck

umount /dev/hdc1
/sbin/e2fsck -c -c -C 0 -D /dev/hdc1

-c -c: marks bad blocks using a non-destructive read-write test
-C 0: prints completion bar

Find world writeable/executable or suid/sgid files

# Find suid/sgid files
find / -type f \( -perm -04000 -o -perm -02000 \) \-exec ls -lg {} \;

# Find world writable files
find / -type f \( -perm -002 \) -exec ls -lg {} \;

# Find world executable files
find / -type f \( -perm -001 \) -exec ls -lg {} \;

# Find unowned files
find / -nouser -o -nogroup

Copy directories over ssh

cd /somedir/somesubdir && tar cpzf - * | ssh somehost "cd /somedir/somesubdir && tar xpzf -"


ssh somehost "cd /somedir/somesubdir && tar cpzf - *" | (cd /somedir/somesubdir && tar xpzf -)

cd/dvd iso files

# make an iso of a dir
mkisofs -r /home/sekhonp/ > image.iso

# make an iso of a cd
dd if=/dev/cdrom of=image.iso bs=10k

# mount iso
mount -o loop,ro -t iso9660 ./image.iso /mnt/iso

# burn an iso to cd
cdrecord -v speed=12 dev=0,0,0 -data image.iso
# or directly
mkisofs -r /home/sekhonp/ | cdrecord -v speed=12 dev=0,0,0 fs=8m -data -

Find the disk usage hog

#Top 20 disk usage hogs on /home
cd /home; du -cks * | sort -nr | head -20


lsof is a very useful diagnostic command:

# show whose listening on sockets
lsof -i -P

# which processes are using a file
lsof /mnt

# which process is holding localhost:80
lsof -i TCP:80

# show handles associated with a process 30563
lsof -p 30563

# show handles associated with a process syslogd
lsof -c syslogd

# show files associated with user sekhonp
lsof -u sekhonp

Grab photos off your mobilephone via bluetooth using obexftp

List photos on phone
obexftp -b 00:1A:75:F1:40:B5 -c "Memory Stick/DCIM/100MSDCF" -l
Grab photos off phone
obexftp -b 00:1A:75:F1:40:B5 -c "Memory Stick/DCIM/100MSDCF" -g DSC00024.JPG

quick ssh script

Create a script called ssh-to like so:
ssh `basename $0` $*
>ln -s ssh-to server1

now to ssh to server1 all you need type is

you can also run commands on server e.g
>server1 ls -al

cvs update all subdirectories

assuming server1.domain.com:/cvs is the cvs repository and you have a whole bunch of cvs modules checked out in /cygdrive/c/sekhonp/it/builds/system1


 echo "Updating system ${1}"
 cd ${1}

 for module in *; do
   if [ -d ${module}/CVS ]; then
     ${cvs} -qq -d :pserver:`whoami`@server1.domain.com:/cvs update -dPA ${module}

update /cygdrive/c/sekhonp/it/builds/system1

unhide shortcuts in windows

attrib /S /D -H "C:\Documents and Settings\All Users\Start Menu\*"

Script to download a tar and extract it if it has changed


export http_proxy=${proxy}

cd ${downloadDir}

modificationTime=`stat -c %y ${tarFile}`
wget -N --proxy=on --proxy-user=${1} --proxy-passwd=${2} --http-user=${3} --http-passwd=${4} ${sourceTarFile}
newModificationTime=`stat -c %y ${tarFile}`
echo "old modification time: ${modificationTime}, new modification time: ${newModificationTime}"

if [ "${modificationTime}" != "${newModificationTime}" ] ; then
echo "Extracting ${tarFile}..."
tar -C ${extractDir} -xzvf ${tarFile} 1>/dev/null

Syncing directories on windows

Here's a little script that syncs a directory using xxcopy

@echo off
REM /BI Backs up incrementally, different (by time/size) files only.
REM /FFn Treats file times within +/- n sec as the same
REM /ZY Deletes extra files or subdirectories in destination, there is no confirmation prompt.
REM /E Copies directories and subdirectories, including empty ones.
REM /H Copies hidden and/or system files also.
REM /R Overwrites read-only files.
REM /KS Keeps the source attributes including the read-only bit.
REM /ZE Disables the use of all Environment Variables for XXCOPY.
REM /YY No prompting
REM /C Continues copying even if errors occur (default).
REM /Q Does not display files which are skipped.
REM /oA append to log file
REM /X excludes files or directories, e.g.

xxcopy "E:\sekhonp\it\builds\bats-system\" "C:\sekhonp\it\builds\bats-system\" /BI /FF30 /ZY /E /H /R /KS /ZE /YY /C /Q /Xclasses\ /X*\classes\ /Xdecompiledsrc\ /X*\dist\ /X*\build\ /Xlog\ /X*.zip

26 June 2006

Vodafone settings

Data accounts

Vodafone GPRS
APN: wap.vodafone.co.uk
Username: wap
Password: wap
Login Request: off
Allow calls: Automatic
IP Address: ...
DNS Address: ...
Authentication: PAP
Data compression: Off
Header compression: Off

Vodafone Internet
APN: internet
Username: web
Password: web
Login Request: off
Allow calls: Automatic
IP Address: ...
DNS Address: ...
Authentication: PAP
Data compression: Off
Header compression: Off

Internet Profiles

Vodafone GPRS
Connect using: Vodafone GPRS
User proxy: Yes
Proxy address:
Port number: 8799

Streaming Settings

Connect using: Vodafone GPRS
Use proxy: No
Proxy address:
Port number: 0

Email Account Settings

Account name: Vodafone UK
Email address: xxxxx
Connect using: Vodafone Internet
Connection type: IMAP4
Incoming server: imap.vodafone.net
Username: xxxxx
Password: xxxxx
Download: Headers & text
Check interval: Off
Outgoing server: send.vodafone.net
Allow connection: Any network
Auto connect: Off
Your name: Parwinder Sekhon
Copy outgoing: off
Encryption: No encryption
Incoming port: 143
Outgoing port: 25

24 June 2006

Corrupt openldap data

So openldap wont start (following a power failure), actually it reports starting succeeds, but the process fails at, or just after, startup. I cd into /var/lib/ldap and enter db_recover, this returns "db_recover: PANIC: fatal region error detected; run recovery". Running slapindex fixes the problem.

23 June 2006

Windows XP Registry Hacks

Applied Inderjeet Singh's Windows XP Registry Hacks

Remove DLLs from loading for applications that are not running anymore
Edit [HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer]
Create a new DWORD value ALwaysUnloadDLL and give it a data value of 1. Reboot.

Place Windows Kernel in RAM
Edit [HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Memory Management]
Set DisablePagingExecutive to 1. Reboot.

Disable 8.3 Name creation in NTFS
Edit HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
Set NtfsDisable8dot3NameCreation to 1. Reboot.

Make network browsing to be faster by preventing checking of remote scheduled tasks
Delete the following registry key: [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\RemoteComputer\NameSpace\{D6277990-4C6A-11CF-8D87-00AA0060F5BF}]. Reboot.

This next hack is not for enhancing performance, but is nonetheless quite useful at times when your system displays an error message at Startup that refuses to go away.
Set NoPopupsOnBoot to 1 (DWORD). Reboot.

For deleting programs from starting up at the boot time: delete their entries from:

For uninstalling unruly programs from "Add Remove Programs" control panel applet, look for the program name in
Also check DisplayName subkey to see tha name of the program.

Displaying Ghosted or nonpresent devices. Open "Command Prompt" and enter the following commands:
SET devmgr_show_nonpresent_devices=1
Now, uninstall hardware devices that are no longer used with your system

23 May 2006

Compress jpeg images using ImageMagick convert

/usr/bin/convert -quality 50 image.jpg image_compressed.jpg

For me this shrunk a 2.8Mb image down to 300K

18 April 2006

ssh tunneling over http

Based on Tunneling SSH over HTTP(S)

Setup ssh tunneling over http with /etc/httpd/conf.d/ssh.conf
ServerName ssh.parwy.net:80
DocumentRoot "/var/www/html"

HostnameLookups On
ProxyRequests on
ProxyVia on

Order allow,deny
Allow from all
And ~/.ssh/config (no intermediate proxy)
Host *.parwy.net
DynamicForward 1080
ProxyCommand /cygdrive/c/sekhonp/tools/proxytunnel/proxytunnel.exe -p ssh.parwy.net:80 -d %h:%p
ServerAliveInterval 30
or ~/.ssh/config (intermediate proxy)
Host *.parwy.net
DynamicForward 1080
ProxyCommand /cygdrive/c/sekhonp/tools/proxytunnel/proxytunnel.exe -p proxyhost:proxyport -u proxyuser -s proxypassword -r ssh.parwy.net:80 -d %h:%p
ServerAliveInterval 30

16 April 2006

A tourist's agenda for London

http://www.londonpass.com/ can be cheaper for intensive visits
http://www.visitlondon.com/city_guide/attractions/f_london_pass.html lists of sites covered

Tower Bridge Exhibition
Duration: 1 hr 30 mins
Address: Tower Bridge London SE1 2UP
Tube: Tower Hill
Tel: 020 7403 3761
Email: enquiries@towerbridge.org.uk
Web: www.towerbridge.org.uk
Opening Times:
Oct-Mar: 0930-1700,
Apri-Sep: 1000-1730
Closed: 24-25 Dec.
Prices: Adult: £5.50, Child: £3.00, Concession: £4.25

Food and drink at The Dicken's Inn St. Katherine's Docks.

Tower of London
Duration: 2 hours
Address: Tower Hill London, EC3N 4AB
Tube: Tower Hill
Tel: 0870 756 6060
Email: nicoleshields@hrp.org.uk
Web: www.tower-of-london.org.uk
Opening Times:
Mar-Oct: Sun-Mon 1000-1700, Tue-Sat 0900-1700.
Nov-Feb: Sun-Mon 1000-1600, Tue-Sat 1000-1600
Closed: 24-26 Dec and 1 Jan.
Prices: Adult: £14.50, Child: £9.50, Concession: £11.00

St Paul's Cathedral
Duration: 1 hour
Address: St Paul's Churchyard London, EC4M 8AD
Tube: St Paul's
Tel: (020) 8340 9591
Email: chapterhouse@stpaulscathedral.org.uk
Web: www.stpauls.co.uk
Opening Times: Mon-Sat, 0830-1630,
Prices: Adult: £8.00, Concession: £7.00, Child: £3.50

London Eye
Duration: 30 minutes
Address: Riverside Building, County Hall Westminster Bridge Road London, SE1 7PB
Tube: Waterloo
Tel: 0870 5000 600
Web: www.ba-londoneye.com
Opening Times:
October-May: 1000-2000,
June-September: 1000-2100
Closed: Christmas Day
Prices: Adult: £13.00, Child: £6.50, Concession: £10.00

London Aquarium
Duration: 2 hours
Address: County Hall Riverside Building London, SE1 7PB
Tube: Waterloo
Tel: 020 7967 8000
Email: pressoffice@londonaquarium.co.uk
Web: www.londonaquarium.co.uk
Opening Times:
1000-1800 (last admission 1700)
Closed 25 Dec. Open times over the Christmas period may vary.
Prices: Adult: £9.75, Child: £6.25, Concession: £7.50

Big Ben

Houses of Parliament (Only summer tours)
Duration: 1 hour 30 mins
Address: Parliament Square, London, SW1A 0AA
Tube: Westminster
Tel: 0870 9063773
Opening Times: Summer opening to be confirmed, late Jul-early Oct
Prices: Adult: £7.00, Child: £5.00, Concession: £5.00

Westminster Abbey
Duration: 30 mins
Address: Parliament Square, London, SW1P 3PA
Tube: Westminster
Tel: 020 7222 5152
Email: info@westminster-abbey.org
Web: www.westminster-abbey.org
Opening Times:
Apr-Oct, Mon-Fri 0930-1545, Sat 0930-1345.
Closed Good Friday and Christmas Day.

Buckingham Palace (Only summer tours)
Duration: 1 hour, 30 minutes
Address: London, SW1A 1AA
Tube: Victoria, St James's Park, Green Park
Tel: 020 7766 7300
Email: bookinginfo@royalcollection.org.uk
Web: www.royalcollection.org.uk
Opening Times: 26 July-24 September 2006 0945-1800 (last admission 15.45). Timed tickets with admission every 15 minutes throughout the day.
Prices: Adult: £14.00, Child: £8.00, Concession: £12.50

Bateaux London Cruise
Classic Lunch 2 course: £19.50, 1200 Embankment or 1235 Waterloo Pier, Nov-Dec Wed-Sat, Jan-Mar Thu-Sat
Classic Dinner: £65, 19:45 Embankment, Nov-Dec Sun-Sat, Jan-Mar Tue-Sat

Covent Garden Market
Leicester Square
Comedy Store


British Museum
National Gallery
Natural History Museum
Science Museum
The Victoria And Albert Museum

Outer London
Thorpe Parke

Backup blogger

I'm backing up this blog site with
wget --directory-prefix=/srv/blog --wait=7 --mirror --ignore-length --page-requisites --convert-links -e robots=off --span-hosts --domains=photos1.blogger.com,parwy.blogspot.com http://parwy.blogspot.com/
some notes:

saves all files to /srv/blog
--mirror: causes it to recurse to any depth and check timestamps to only download newer files
--ignore-length: blogger seems to report a different length for files which causes wget to download files that havent changed
-e robots=off: without this any phots at photos1.blogger.com are not downloaded, as this site has a robots file which prevents any crawling, since I'm only crawling over photos I link to, its okay to disable

Some typical java vm parameters

-agentpath:"C:\Program Files\YourKit Java Profiler 5.1.1\bin\win32\yjpagent"

Directions to 14 Rutlish Road

Directions from MultiMap

Directions from M25

  1. Get off M25 on Junction 10, onto A3 towards Central London

  2. Stay on A3 for about 15 minutes, until you see signs for the A298 towards Wimbledon/Merton Park. You will be going towards Merton Park.

  3. After 5-10 minutes, you will pass Wimbledon Chase station on your left, while going under a bridge, then a few minutes later, the Nelson Hospital on your right.

  4. After a further few minutes, you will go over some traffic lights which cross a tram line, on your right will be a large cream coloured pub called the White Hart. Turn right here onto Rutlish Road and down to the end of the street.

Roadmap of 14 Rutlish Road

15 April 2006

Backup del.icio.us

wget --http-user=delicious-user --http-passwd=delicious-pass -O bookmarks-delicious.xml http://del.icio.us/api/posts/all


Here is a modified version of the LDIF to VCARD script by Scott Barninger at http://www.barninger.com/ldif_to_vcard/.

Its adds a lot more fields, its adds some escaping of special characters:
$VERSION = "0.2.0";
use Net::LDAP::LDIF;

# declarations

$ldif = Net::LDAP::LDIF->new(\*STDIN);

while($entry = $ldif->read()) {
$common_name = &escape($entry->get_value('cn'));
$first_name = &escape($entry->get_value('givenName'));
$last_name = &escape($entry->get_value('sn'));
$org_name = &escape($entry->get_value('o'));

$email = &escape($entry->get_value('mail'));
$url = &escape($entry->get_value('url'));

$homephone = &escape($entry->get_value('homePhone'));
$workphone = &escape($entry->get_value('telephoneNumber'));
$mobilephone = &escape($entry->get_value('mobile'));
$fax = &escape($entry->get_value('facsimileTelephoneNumber'));

$address = $entry->get_value('postalAddress');
$address =~ s/\\/\\\\/g;
$address =~ s/;/\\;/g;
$address =~ s/\r\n|\n|\r/\\, /g;
$city = &escape($entry->get_value('l'));
$state = &escape($entry->get_value('st'));
$postcode = &escape($entry->get_value('postalCode'));
$country = &escape($entry->get_value('c'));

$categories = $entry->get_value('categories');
# ldap contains semi-colon seperated list, vcard requires comma seperated list
$categories =~ s/,/\\,/g;
$categories =~ s/;/,/g;

$note = $entry->get_value('description');
$note =~ s/\\/\\\\/g;
$note =~ s/\r\n|\n|\r/\\n/g;

($sysdate,$systime) = &sys_date;

# only output relevant records, should really check objectclass
# if($homephone || $workphone || $mobilephone) {
print "BEGIN:VCARD\r\n";
print "VERSION:3.0\r\n";

print "FN:$common_name\r\n";
if($first_name || $last_name){
print "N:$last_name;$first_name\r\n";
# print "N:;$common_name\r\n";
print "ORG:$org_name\r\n";

print "EMAIL;TYPE=INTERNET,PREF:$email\r\n";

print "URL;TYPE=WORK:$url\r\n";
} else {
print "URL;TYPE=HOME:$url\r\n";


print "TEL;TYPE=WORK:$workphone\r\n";
print "TEL;TYPE=HOME:$homephone\r\n";
print "TEL;TYPE=CELL:$mobilephone\r\n";
print "TEL;TYPE=FAX:$fax\r\n";

if($address || $city || $state || $postcode || $country){
print "ADR;TYPE=WORK:;;$address;$city;$state;$postcode;$country\r\n";
} else {
print "ADR;TYPE=HOME:;;$address;$city;$state;$postcode;$country\r\n";

print "CATEGORIES:$categories\r\n";

print "NOTE:$note\r\n";

print "REV:$sysdate" . "T$systime\r\n";

print "END:VCARD\r\n";
# }


sub escape {
local($a) = ($_[0]);
$a =~ s/\\/\\\\/g;
$a =~ s/;/\\;/g;
$a =~ s/,/\\,/g;
return $a

sub sys_date {
# get the system date
# usage: my($sysdate,$systime) = &sys_date;

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
if (length ($min) == 1) {$min = '0'.$min;}
if (length ($sec) == 1) {$sec = '0'.$sec;}
# since localtime returns the month as 0-11
$mon = $mon + 1;
if (length ($mon) == 1) {$mon = '0'.$mon;}
if (length ($mday) == 1) {$mday = '0'.$mday;}
# since localtime returns the year as the number of years since 1900
# ie year is 100 in the year 2000 (so is y2k OK)
$year = $year + 1900;
my $date = "$year-$mon-$mday";
my $time = "$hour:$min:$sec";

14 April 2006

Hello World

The title says it all, lets see if I ever get to post another entry again!