Mar 16 2009

In Australia we are in the unfortunat…

Category: Programminglomaxx @ 9:00 am

In Australia we are in the unfortunate situation where no matter where you are, you have to pay line rental for your landline phone. Then on top of that you have to pay for your phone calls. The catch was that even though I didn’t use my home phone for phone calls, I had no choice but to pay line rental because my ADSL connection relies on the phone line. Even more annoying is the fact that I have VoIP hooked up through PennyTel so even if I did use my home line, I wouldn’t be using the private carrier.

So, my monthly "Telecommuncations" bill looked like this:

  • $49.95 for my internet connection through netspace (40gb Downloads)
  • $29.95 line rental
  • $5.00 per month contract with PennyTel (plus calls)

Which left me with a total bill of $84.90 and feeling like I wasn’t getting great value.

It was also a pain because there was 3 different bills and it was just generally a hassle.

For a while now, Australian ISP’s have been offering "Naked" ADSL plans which effectively allow you to have an ADSL connection through your phone line without paying line rental. It’s not quite how it works, because you do pay a premium for the "Naked" plans. Recently Netspace released their Naked ADSL plans and for me, it worked out being cheaper and better value than ADSL with line rental. I now just have a Netspace bill and a PennyTel bill which I like.

So now my monthly "Telecommunications" bill looks like this:
  • $74.95 for ADSL through netspace (50gb downloads)
  • $5.00 per month contract with PennyTel (plus calls)

I now have a total bill of $80 / month and it’s only a $5 / month saving, however I do get more downloads and I don’t feel like I’m paying for something I’m not even using.


Mar 13 2009

Documentation is Hard… but you should still do it

Category: Programminglomaxx @ 11:04 am

One of the things I struggle with is documentation. Jeff Atwood and Mike Pope both suggest that “if it’s not documented it doesn’t exist ” and I have to agree. Despite knowing how important good documentation is, it often gets put down the priorities list as deadlines approach. So recently I that enough was enough and decided to set aside a day to catch up on my documentation. My goal was to try and document the systems I had been working on recently and I figured that a day would be plenty. 

I fired up our documentation wiki and was all ready to write down everything I knew about the systems but after an hour I’d achieved very little. After 2 hours I’d deleted everything and wanted to start again.

I couldn’t understand what the problem was. I had a hand in designing and writing the systems so I knew plenty about them. I’d been working on the systems up until the previous day so the code was still fresh in my mind. I generally don’t have too much difficulty trying to articulate what I want to say and yet I was struggling to put into words anything that I felt would be any help to anyone.
I thought if I just sat down and made a conscious effort to write documentation the rest would be easy. Turns out I was wrong. Maybe the reason I’ve been lax about documentation in the past wasn’t because I didn’t like it, but maybe it’s because it’s just damn hard.
After some contemplation I realised that I hadn’t put any planning into what I wanted to document so I came up with these rough guidelines:
  1. Identify your target audience. You may find that you need to write different documents to appeal to different audiences. Developers will need different information to BA’s. Trying to make your documentation appeal to everyone will end up in a document that isn’t very useful to anyone.

  2. Work out a rough structure before you start. Try and spend 10 minutes working out a rough outline of what you want to include in your documentation. Doing this will help you structure your thoughts as you’re writing.
  3. You’re final document can be as big as you want but try to keep each section within the document small and relevant. Try not to include details that are irrelevant.
  4. Identify what parts of the documentation are most important and focus on those first.
  5. Get someone from your to look over what you’ve written to make sure it makes sense to them. The documentation is every bit as much for them as it is for you
  6. Isolate yourself. Turn of email, unplug your phone, whatever. Just avoid yourself getting distracted as you’re going to need every bit as much mental concentration to write your documentation as you did to write the systems you’re documenting.
I strongly believe that developers should be responsible for writing their own documentation too. Who better to write the documentation for the system than the person who created it?


Mar 12 2009

RescueTime

Category: Programminglomaxx @ 9:14 am

I downloaded and installed RescueTime recently after reading about it on Tim Ferriss’ blog.
It’s a neat little application that keeps track of where you’re spending your time on your computer. It’s important to me that I know where I’m spending my time but the only way to be able to analyse where my time is going is by collection hard evidence. Since installing the personal version of RescueTime I’m already noticing that I’m actively thinking a lot more about where I can spend my time productively, so from that perspective, it’s a win. It has also highlighted that there’s a lot of time during my day where I’m literally just wasting time in front of the screen. I’ve found myself become more and more aware of it and now, instead of just burning more screen time, I’m more inclined to stop and either get back to doing something productive or take myself away from the computer completely to stop myself going stale.

 
I’m only using the personal version at the moment but it’s chock full of features including detailed stats of where you’re using your time, the ability to set goals and alerts and to track stats from multiple computers.
 
I also really like how polished the application is. It doesn’t have any bells and whistles in terms of UI, but it seems to me like the team has spent a lot of time focusing on the core features of RescueTime and making sure they work well.
 
If you’d like to see where your time is going on your computer, I’d thoroughly recommend RescueTime.

 


Mar 09 2009

Interfacing with Interfaces

Category: Programminglomaxx @ 2:13 pm

I had an interesting email discussion with a colleague about how interfaces should be used in our codebase the other day and it made me think about the role of interfaces in code. To give a bit of background information I’m a big fan of interfaces and like to use them wherever it makes sense. The question my colleague and I were having was about how I have a tendancy to define an interface even though there is only a single implementation of the interface.

My first response was that it allowed classes to be de-coupled from each other as per the Dependency Invesion principle which states you should depend on abstractions rather than concrete implementations. Despite being perfectly valid, I felt it was a little weak if that was the only reason.

Thinking about it a little longer I realised that the most common usage for an interface was when you needed to have multiple custom implementations of an object that could be used in common scenarios. For example you might have an IEmployee object that would be implemented by multiple employee classes. This had gradually evolved into a design mindset that encourages people to only use interfaces when there is an immediate need for multiple implementations of a common object. The danger with this mindset is that people tend to forget that an interface is nothing more than a contract for implementers. It does not imply that it is a contract that will be implemented by more than one class.

Karl Seguin’s article on interfaces words it nicely:

The role of an interface is to define the contract that implementers must follow

Nothing more, nothing less. It’s just a contract. Just because you are only implementing the contract once now, doesn’t mean that you should do away with the interface. In fact, providing interfaces for single implementations of classes may well save you time in the future because if you have to re-implement the class, having an interface means you’ll know in advance exactly what needs to be implemented.

In any case, don’t be afraid to use interfaces to define contracts even if you only have a single initial implementation.


Mar 06 2009

System.InvalidOperationException: Sequence contains no elements

Category: Programminglomaxx @ 4:20 pm

I had and interesting experience with the Linq Min method today. I got an error in production saying

System.InvalidOperationException: Sequence contains no elements at System.Linq.Enumerable.Min[TSource](IEnumerable`1 source)

It was produced by this line of code:

DateTime minDate = parcels.Min(p => p.StartDate)

I have to admit I was a little taken aback by this error because it’s a fairly innocent looking line of code. But upon further consideration it’s actually a fairly dangerous line of code. If you have a parcels collection that has no elements, you can get yourself into some pretty serious trouble and the Min function will throw the System.InvalidOperationException. At first glance you might think that if there are no parcels in the collection it should just return null, however if you think about it, this isn’t the correct behaviour because null isn’t a valid value for something that is supposed to be a “minimum”.

The answer of course is to check that the collection does have one or more elements before you call the Min function however it was an interesting look at how dangerous making assumptions can be when working with what looks like trivial code.


Jan 16 2009

Iron Speed Designer Licensing Issues

Category: Programminglomaxx @ 1:56 pm

I’ve been using Iron Speed designer for a number of years and generally have had nothing to complain about. That was until 2 weeks ago when Iron Speed decided that I was using my license illegally and PERMANENTLY DISABLED my license.

They had basically decided that I was using my license key illegally and without consultation or warning canceled my license key. 

To understand the full story, you’ll need a bit of background information. The way Iron Speed activation works is that when you purchase a license you have to activate the license with Iron Speeds central activation server. When you want to use the license on another machine, you need to de-activate it on the current machine and re-activate it on the second machine.

This is an extremely annoying process, but at it’s better than not being able to activate your license on another machine.

This activation process isn’t flawless either. For example, on the Iron Speed website, they outline the backup procedure they want you to use. This is fine, however there is a situation where you can get yourself into trouble (like I did). The backup procedure backs up the activated license file so you can restore the license onto your machine and continue working. It’s really important you do this because if you somehow lose the data on that machine, you can’t activate a new installation of Iron Speed because the server already thinks you have an active license. Let me break the process down into some easier to understand steps:

  1. You purchase the license and activate it.
  2. You backup your data with the activated license.
  3. Your hard drive dies and you lose everything on the machine, including your Iron Speed Installation.
  4. You re-install Iron Speed but because you didn’t de-activate the copy before your hard drive crashed, you can’t re-activate it.
  5. You restore your backup copy of Iron Speed that you activated before the machine crash and everything is ok.

So far so good… however you have to be careful. If you haven’t worked it out yet, this actually provides a way to have Iron Speed activated on multiple machines at once without actually realising. My scenario basically played out like this:

  1. I installed Iron speed on Machine A
  2. I Activated it and then took a Norton Ghost image
  3. I then de-activated Iron Speed on Machine A
  4. I then activated Iron Speed on Machine B
  5. After a few months, I formatted Machine A and restored the Ghost Image with the Active Version of Iron Speed.
  6. I now had 2 active versions of Iron Speed on my one license.

The scenario is a little more complicated than that, however that is the short version of the steps that led up to the following.

Without warning or consultation of any sort, the powers that be at Iron Speed decided to DISABLE my license.

The thing that worries me most about this is that Iron Speed doesn’t disclose on their website anywhere that they are able to disable your license. They don’t even so much as mention that they log all usage of Iron Speed. During my emails back and forth between Iron Speed and myself, I found out that they log all usage of all instances of Iron Speed, not just activations and de-activations. They also log the IP addresses that the usages come from.

So after numerous emails explaining exactly my situation and being completely up front with Iron Speed, they still won’t re-activate my license. Remember this is a license that I purchased and now am no longer able to use due to a fairly honest mistake. I was in the process of considering whether to upgrade my license to Iron Speed 5.2 or not, but as it turns out I will never be dealing with Iron Speed again.

The point is, that if you make licensing hard, you’re going to end up losing customers. Same goes for purchasing as Ayende points out. I fully understand that Iron Speed is a business and they need to make money, but annoying customers is hardly a good way to do it.

It kind of reminds me of a post where Jeff Atwood recommends a few suggestions for avoiding piracy:

In fact, the most effective anti-piracy software development strategy is the simplest one of all:

  1. Have a great freaking product.
  2. Charge a fair price for it.

I think adding a third to that list probably wouldn’t go astray:

    3. Don’t punish paying customers for using your product

 


Jan 12 2009

NHibernate Components and Null Values

Category: Programminglomaxx @ 9:22 am

There’s a feature in NHibernate that allows you the map a series of related columns in a table into a smaller class called a component.

A common use for components is to have an employee record with a ContactDetails subclass and group all the contact details into a component which is mapped to the ContactDetails subclass.

This is all pretty straightforward however there’s one little gotcha that you need to be aware of. The NHibernate documentation states that:

Like all value types, components do not support shared references. The null value semantics of a component are ad hoc. When reloading the containing object, NHibernate will assume that if all component columns are null, then the entire component is null. This should be okay for most purposes.

The section in bold is particularly important because NHibernate makes the assumption that if all the columns in the component are null then the compent itself is null. When using components you need to make sure that your code caters for this situation. The main concern you will have is assigning a value to the component when it is null, so you’ll have to make sure that all assignments to a component check for null.

Otherwise, components are a pretty cool feature.


Dec 31 2008

Blogging From Google Docs

Category: Programminglomaxx @ 7:58 am

So I haven’t been blogging for a while because there’s been a couple of restrictions.
First, I haven’t had time.

Second I was primarily using Word 2007 to publish posts to my blogs, however since I started working onsite, I haven’t been able to use word 2007 to connect through the corporate firewall at the site I’m working at.

Today tho, I was playing with google docs and I noticed the "Publish" feature for documents. After a bit of digging I discovered that you could publish direct to my blog from google docs. This is great because it greatly reduces the friction that was created by not having access to publish blogs from word 2007.

Publishing pictures is still going to be slightly annoying tho, because I used to just create screen shots and paste them straight into word, where as now I’ll have to save the images then upload them, but it’s still infinitely easier than using the annoying editor in wordpress.

Hopefully in the long term tho, it’ll mean an increase in blog posts.

 


Aug 08 2008

Somebody needs to think about the quality

Category: Programminglomaxx @ 9:20 am

Dare Obasanjo had a great blog post the other day on the second system effect. One of the points he makes is

You Can be Date Driven or Feature Driven but not Both

He goes on to say why you can’t be both, but he doesn’t really touch on the fallout of running a project which is both feature and date driven. I recently worked on a project that was both feature and date driven and when you can’t comprimise features or the deadline, you have to comprimise somewhere else. That somewhere else is Quality.

We ran into a couple of problems mid project that put us about a week behind schedule, but unfortunately we weren’t given any more time and features weren’t dropped. What we ended up doing was getting rid of the unit tests in our code, getting rid of 1 week UAT and there was no documentation.

Now there are people that read this and think "well if you have to ship, you’re going to have to comprimise somewhere", but if these are the places you comprimise you are playing a very dangerous game.

By compromising all these areas, you’re reducing the quality of the work that you produce and it means you’re taking a massive risk.

When you’re working on projects, you need to realise that setbacks are going to arise and almost always the correct course of action isn’t to cut the quality out of what you’re doing because it’s only going to burn you in the long run. You need to sit down and seriously evaluate what this setback means and look at every other area you can comprimise before you start cutting back on quality. Doing so not only increases the quality of the project but increases the chances of having a successful outcome to your project


Jul 30 2008

Do we really need comments in code?

Category: Programming, Theorieslomaxx @ 10:00 am

Recently Jeff Atwood posted about Coding without Comments. Not only do I agree with Jeff’s post, I would actually like to see comments removed from code altogether. The other day I was working with the amazing FileHelpers library from Marcos Meli and needed to dig into the code to add some extra functionality. Now I’m not having a go at Marcos, or the library itself, but I’m just using this as an example because it highlights exactly the problem I have with comments in code:

 

#region "  © Copyright 2005-07 to Marcos Meli - http://www.devoo.net"
// Errors, suggestions, contributions, send a mail to: marcos@filehelpers.com.

#endregion
#if ! MINI
using System;
using System.Data;
using System.Data.SqlClient;

namespace FileHelpers.DataLink
{
    /// <summary>This is a base class that implements the <see cref="DataStorage"/> for Microsoft SqlServer.</summary>
    public sealed class SqlServerStorage : DatabaseStorage
    {

        #region "  Constructors  "

        /// <summary>Create a new instance of the SqlServerStorage based on the record type provided.</summary>
        /// <param name="recordType">The type of the record class.</param>
        public SqlServerStorage(Type recordType)
            : this(recordType, string.Empty)
        {}

        /// <summary>Create a new instance of the SqlServerStorage based on the record type provided.</summary>
        /// <param name="recordType">The type of the record class.</param>
        /// <param name="connectionStr">The full conection string used to connect to the sql server.</param>
        public SqlServerStorage(Type recordType, string connectionStr)
            : base(recordType)
        {
            ConnectionString = connectionStr;
        }

        /// <summary>Create a new instance of the SqlServerStorage based on the record type provided (uses windows auth)</summary>
        /// <param name="recordType">The type of the record class.</param>
        /// <param name="server">The server name or IP of the sqlserver</param>
        /// <param name="database">The database name into the server.</param>
        public SqlServerStorage(Type recordType, string server, string database)
            : this(recordType, server, database, string.Empty,string.Empty)
        {
        }

        /// <summary>Create a new instance of the SqlServerStorage based on the record type provided (uses SqlServer auth)</summary>
        /// <param name="recordType">The type of the record class.</param>
        /// <param name="server">The server name or IP of the sqlserver</param>
        /// <param name="database">The database name into the server.</param>
        /// <param name="user">The sql username to login into the server.</param>
        /// <param name="pass">The pass of the sql username to login into the server.</param>
        public SqlServerStorage(Type recordType, string server, string database, string user, string pass)
            : this(recordType,  DataBaseHelper.SqlConnectionString(server, database, user, pass))
        {
            mServerName = server;
            mDatabaseName = database;
            mUserName = user;
            mUserPass = pass;
        }

        #endregion

        #region "  Create Connection and Command  "

        /// <summary>Must create an abstract connection object.</summary>
        /// <returns>An Abstract Connection Object.</returns>
        protected sealed override IDbConnection CreateConnection()
        {
            string conString;
            if (ConnectionString == string.Empty)
            {
                if (mServerName == null || mServerName == string.Empty)
                    throw new BadUsageException("The ServerName can´t be null or empty.");

                if (mDatabaseName == null || mDatabaseName == string.Empty)
                    throw new BadUsageException("The DatabaseName can´t be null or empty.");

                conString = DataBaseHelper.SqlConnectionString(ServerName, DatabaseName, UserName, UserPass);
            }
            else
            {
                conString = ConnectionString;
            }

            return new SqlConnection(conString);
        }

        #endregion

        #region "  ServerName  "

        private string mServerName = string.Empty;

        /// <summary> The server name or IP of the SqlServer </summary>
        public string ServerName
        {
            get { return mServerName; }
            set
            {
                mServerName = value;
                ConnectionString = DataBaseHelper.SqlConnectionString(ServerName, DatabaseName, UserName, UserPass);
            }
        }

        #endregion

        #region "  DatabaseName  "

        private string mDatabaseName = string.Empty;
        /// <summary> The name of the database. </summary>
        public string DatabaseName
        {
            get { return mDatabaseName; }
            set
            {
                mDatabaseName = value;
                ConnectionString = DataBaseHelper.SqlConnectionString(ServerName, DatabaseName, UserName, UserPass);
            }
        }

        #endregion

        #region "  UserName  "

        private string mUserName = string.Empty;
        /// <summary> The user name used to logon into the SqlServer. (leave empty for WindowsAuth)</summary>
        public string UserName
        {
            get { return mUserName; }
            set
            {
                mUserName = value;
                ConnectionString = DataBaseHelper.SqlConnectionString(ServerName, DatabaseName, UserName, UserPass);
            }
        }

        #endregion

        #region "  UserPass  "

       private string mUserPass = string.Empty;
        /// <summary> The user pass used to logon into the SqlServer. (leave empty for WindowsAuth)</summary>
        public string UserPass
        {
            get { return mUserPass; }
            set
            {
                mUserPass = value;
                ConnectionString = DataBaseHelper.SqlConnectionString(ServerName, DatabaseName, UserName, UserPass);
            }
        }

        #endregion

        #region "  ExecuteInBatch  "

        /// <summary></summary>
        protected override bool ExecuteInBatch
        {
            get { return true; }
        }

        #endregion

    }
}

#endif

There are 167 lines of  "code" in this example

However, if you remove the comments and regions and have a quick re-organisation of the code you can reduce this file down to 110 lines of just raw code:

#region "  © Copyright 2005-07 to Marcos Meli - http://www.devoo.net"

// Errors, suggestions, contributions, send a mail to: marcos@filehelpers.com.

#endregion

#if ! MINI
using System;
using System.Data;
using System.Data.SqlClient;

namespace FileHelpers.DataLink
{
    public sealed class SqlServerStorage : DatabaseStorage
    {
        private string mServerName = string.Empty;
        private string mDatabaseName = string.Empty;
        private string mUserName = string.Empty;
        private string mUserPass = string.Empty;

        public SqlServerStorage(Type recordType)
            : this(recordType, string.Empty)
        {}

        public SqlServerStorage(Type recordType, string connectionStr)
            : base(recordType)
        {
            ConnectionString = connectionStr;
        }

        public SqlServerStorage(Type recordType, string server, string database)
            : this(recordType, server, database, string.Empty,string.Empty)
        {
        }

        public SqlServerStorage(Type recordType, string server, string database, string user, string pass)
            : this(recordType,  DataBaseHelper.SqlConnectionString(server, database, user, pass))
        {
            mServerName = server;
            mDatabaseName = database;
            mUserName = user;
            mUserPass = pass;
        }

        protected sealed override IDbConnection CreateConnection()
        {
            string conString;
            if (ConnectionString == string.Empty)
            {
                if (mServerName == null || mServerName == string.Empty)
                    throw new BadUsageException("The ServerName can´t be null or empty.");

                if (mDatabaseName == null || mDatabaseName == string.Empty)
                    throw new BadUsageException("The DatabaseName can´t be null or empty.");

                conString = DataBaseHelper.SqlConnectionString(ServerName, DatabaseName, UserName, UserPass);
            }
            else
                conString = ConnectionString;

            return new SqlConnection(conString);
        }

        public string ServerName
        {
            get { return mServerName; }
            set
            {
                mServerName = value;
                ConnectionString = DataBaseHelper.SqlConnectionString(ServerName, DatabaseName, UserName, UserPass);
            }
        }

        public string DatabaseName
        {
            get { return mDatabaseName; }
            set
            {
                mDatabaseName = value;
                ConnectionString = DataBaseHelper.SqlConnectionString(ServerName, DatabaseName, UserName, UserPass);
            }
        }

        public string UserName
        {
            get { return mUserName; }
            set
            {
                mUserName = value;
                ConnectionString = DataBaseHelper.SqlConnectionString(ServerName, DatabaseName, UserName, UserPass);
            }
        }

        public string UserPass
        {
            get { return mUserPass; }
            set
            {
                mUserPass = value;
                ConnectionString = DataBaseHelper.SqlConnectionString(ServerName, DatabaseName, UserName, UserPass);
            }
        }

       protected override bool ExecuteInBatch
        {
            get { return true; }

       }

    }
}

#endif

 

The thing that strikes me is that the code has been written so well that it’s perfectly clear what is happening in this class and you also have the added benefit of having a much more readable section of code.

Going back to the first sample of code, a lot of the original comments are what I would consider documentation. I agree that’s it’s important to document code, but is it really necessary to do it within the code itself?

I was discussing this with a co-worker the other day and we both agreed that a really cool feature in visual studio is to have some way of hiding comments within the IDE and placing a little token or tag in the margin of the page which would show the comments for the code when you hovered over them. Even better, would be to abstract comments out into another file, like code.comments.cs or code.comments.xml so that if people have a burning desire to comment on the code, they still can, but it just won’t be cluttering up the actual code files.

In reality, I’m still going to get beaten up in my day job for not having enough comments in my code, but I will still be pushing for less comments in code and better refactoring and documentation to support the code.


« Previous PageNext Page »