Programming for someone with blinders

One of your goals as a developer should be to make your code as readable as possible, both for yourself, and for the other developers you work with.

Horse with Blinders

One great way to determine if your code is well written, is to ask yourself if the code you’re writing is readable by itself. Another developer should be able to jump into a module, and have a fairly easy time seeing what’s going on. They shouldn’t have to sift through thousands of lines of interweaved code to figure out what’s going on.

Of course, what I’m talking about is simply a test for the single responsibility principle. If you’ve written a huge "do it all" class with thousands of lines of code, you’re ensuring that you’re the only one that will be able to maintain it. That that type of code usually suffers from high coupling to the other modules in the program.

I used to organize code into classes based on the type of functionality being provided. I used them more as containers for related functionality. At the time, I didn’t see a reason to split it apart. I was very wrong.

In a recent article by Jimmy Bogard, he walks through creating classes with a separation of concerns. In the conclusion is my favorite part:

Now we have many more classes (4 vs. 1) and interfaces (3 vs. 0).  For those who don’t like more classes, GET OVER IT.

That is an excellent point. Why should you be afraid of creating more classes and interfaces? It’s really not more code to write, in fact, it’s often less. Refactoring tools remove many of the obstacles of maintaining the interface, class, and method structure

When someone looks at your code and you have 4 classes instead of 1, and those classes are very specific and short enough to process by our tiny brains, it will be much easier to maintain and modify (or even better, extend).

Locking sessions for multi-threaded access

I recently ran into a situation where I needed to upload some small files from a Flex client application to an ASP.NET web server. I decided to store the uploaded files in the users session while they were in the checkout process. Once the user confirms their order, the images are read from the session and stored to the database.

Here is the original code from the page that accepts each uploaded file, and adds it to a Dictionary in the collection:

if (Session[SESSION_ORDER_FILES] == null)
{
	//Our dictionary hasn’t been created, so we do it now
	files = new Dictionary<string, byte[]>();
	Session[SESSION_ORDER_FILES] = files;
}
else
{
	//The dictionary has already been created, just load it
	files = (Dictionary<string , byte[]>) Session[SESSION_ORDER_FILES];
}

//If we have the "_clearPrevious" flag, that means all
//of the files should be removed from this users session
if (_clearPrevious)
	files.Clear();

//If the file name is the same, replace it
if (files.ContainsKey(_fileName))
	files.Remove(_fileName);

files.Add(_fileName, bytes);

The problem is that we ended up with missing images. The client was sending them, but when the user confirmed their order they were missing images in the session. Since ASP.NET will process page requests in multiple threads, the session can be accessed in multiple threads!

Now, we need to find a way to lock them. I questioned whether ASP.NET would give me the same session object each time, or a new instance representing the same session. I whipped up this code in a test page. It saves the previous session reference to the session. I know it’s a little strange, but since no serialization happens with the session, it gave me a good way to know if the previous session object and the current session object were the same instance.

const string SESS_SESS = "test";
var currSessionObj = Session[SESS_SESS];

if(currSessionObj == null)
	//First page load
	Session[SESS_SESS] = Session;
else
	lblText.Text = (Session[SESS_SESS] == Session).ToString();

The result of this page was false. That means you most certainly do get a new session instance each time. Keep in mind that I’m not saying it’s a different session, the object you’re accessing the session with simply changes.

What does this mean?

This means that you have to be careful when there is a chance that you’re working with session objects in multiple pages, or in a page that could be accessed multiple times simultaneously. Thankfully, there are only a few real-world scenarios where this would be a large concern.

As with any other kind of multi-threaded code, be careful if you’re checking the session, and then performing an action based on the result. In that case, you’ll need to lock a global object that is available to all threads that could access that code. Here is an example:

lock(Global.SessionLock)
{
	if(Session["foo"] == null)
		Session["foo"] = new Bar();
}

In your Global class, you’ll need this field:

static object SessionLock = new object();

Using objects or repository interface in constructor

I’ve been really trying to use the Single Responsibility Pattern in all of the classes I design. Recently, I needed to create code to query a list of holidays from the database, and then create a method that allows you to get the number of holidays between two given dates.

Here was my first stab at the constructor:

public HolidayCalculator(IEnumerable<DateTime> holidays)

It’s simple and easy to understand. Then I started thinking about some of the dependency injected examples I’ve seen. For example, one of the Spring.NET IoC quickstarts has a similar example, except that they’re trying to list movies. In their example, they use an IMovieFinder interface. That interface has a single method that retrieves a list of movies. Using this concept, my constructor would look like (and what I ultimately changed it to):

public HolidayCalculator(IHolidayRepository holidayRepository)

That example originally seemed unnecessarily complex to me. Why separate something so simple and disconnected into an interface? Well, it turns out there are a couple of good reasons that you might want to do this.

Delay loading

With my original constructor, I had to load all of the holidays from the repository (ultimately a database in the production environment) to even create an instance of this class. This is certainly less than ideal when I want to use this class as a singleton that may get created early in the application.

Single Responsibility

In my original design, I was accepting in a list that would get cached in my holiday calculator. My class now has two responsibilities. It has to calculate holidays, and it has to cache the holiday list. What if I wanted to change how the list was cached? I would have to change the class, which is not ideal.

Holiday-Calculator-Design

Ideally, this class would load the holiday list each time it needs to perform a calculation. The implementation passed into the constructor would be responsible for caching. In fact, we can now easily separate out the caching feature, and the holiday loading feature. Both classes would implement the IHolidayRepository interface and would be chained together. The caching class would take an IHolidayRepository.

Incremental Coding

Following the Agile philosophy, I can now deliver code faster. I don’t need to add a caching layer. I can have a working application in less time, and then later evaluate if I need to cache the holiday data.

Conclusion

Overall, this design is a little more work, but I think the benefits outweigh the extra classes and interface I needed to create. This design makes it easy to test, and each class has almost no code in it. Reading it and understanding it is extremely simple.

What every manager needs to ask and know

I’ve read books about what makes employees happy. If you manage people, I recommend reading the book First, Break all the rules - What the world’s greatest managers do differently. In that book, they surveyed tends of thousands of the best managers and employees. In their extensive research, they were able to come up with the 12 most important factors that make employees happy, increase productivity, and decrease turn-over.

First, break all the files, what the world's greatest managers do differently

  1. Do I know what is expected of me at work?
  2. Do I have the materials and equipment I need to do my work right?
  3. At work, do I have the opportunity to do what I do best every day?
  4. In the last seven days, have I received recognition or praise for good work?
  5. Does my supervisor, or someone at work, seem to care about me as a person?
  6. Is there someone at work who encourages my development?
  7. At work, do my opinions seem to count?
  8. Does the mission/purpose of my company make me feel like my work is important?
  9. Are my co-workers committed to doing quality work?
  10. Do I have a best friend at work?
  11. In the last six months, have I talked with someone about my progress?
  12. At work, have I had the opportunities to learn and grow?

A major point of the book is that managers are able to read employees, and treat each of them in a way that makes them happy and productive. That may mean that one person gets 5 monitors, and another gets an Optimus keyboard. Another employee may have to move into the basement, and give up their red stapler.

My opinion is that managers work for their employees. It’s the managers job to make sure the employees are productive, and to provide the right environment. If they can’t do that, they shouldn’t be a manager.

Lately, I’ve began wondering why managers don’t ask each employee this simple question:

"What do you need from me?"

If you’re manager doesn’t ask this, are they just guessing? In some cases the answers may not be incredibly useful, but in most cases you could learn a lot from the answer. For example, someone might say they need it to be quiet, and another might say they need a lot of background noise. A person might say that they need flexible hours or more desk space.

If you don’t ask that question, you may never know the answer. If you’re lucky, you’ll eventually be able to figure it out, but can you afford to take that chance?

If your manager doesn’t ask this question, why don’t you answer it anyway? Even if it doesn’t help your manager, it will certainly help you understand what you need to accomplish your goals. You may be able to find more creative ways to help your manager understand what you need to get your job done.

New Backup Solution - JungleDisk + Amazon S3

I’ve settled on a new backup solution. I’m going to be using Amazon’s persistent storage solution called S3. Amazon provides a virtually infinite, scalable storage cloud that allows you to store files indefinitely. You pay a small fee to get the data there ($.10/gig), a fee to store the data ($.15/gig/month), and a fee to retrieve the data ($.17/gig).

Features I was looking for:

  • Reasonably Priced
  • Automatic
  • Reliable
  • Scalable
  • Well performing
  • Easy

Price

To automate my backups, I’m using a product called JungleDisk. You can purchase it for $20, and you get free upgrades for life. I love products that have free upgrades for life, since I don’t have to worry about when buy it. They also allow you to use it on unlimited computers, which I definitely need.

JungleDisk by default talks directly with S3, so they don’t need to run any servers. You’re counting 100% on the reliable storage provided by S3.

Organization

Amazon stores your files in "buckets", which you can think of as a single level folder/directory structure. JungleDisk can easily connect to multiple buckets at the same time. You configure each bucket independently. JungleDisk can automatically detect all of your buckets, and you can easily create new ones.

image

I highly recommend creating buckets for each logical group of files you want to back up. Try to avoid sharing a bucket between computers when possible. If you tell JungleDisk that a bucket is only used on one computer, it doesn’t have to query S3 to determine what needs to be synchronized. The default is set to multiple computers. This setting is under the "Bucket Settings" for each bucket.

image

Each bucket also lets you choose what to back up. Of course there are extensive options for backing up subfolders, excluding files, etc.

image

You can even set up how your local folders get mapped to the remote folders. This lets you do multiple folders in one bucket. On my laptop, I have a couple of folders that get backed up to a single bucket, but are organized into different folders so that I could easily restore them independently.

image 

Scheduling

Setting up a schedule is very easy. For example, on my laptop, I have it set to synchronize my files every hour. It uses the timestamp’s of the files to determine if there are any new, changed, or deleted files. Since I’m not sharing this particular bucket between machines, it can instantly determine if anything needs backed up.

image

 image

Security

JungleDisk has all the security options you would expect. You can communicate with Amazon over port 80 unencrypted, or use SSL. I actually turn off the SSL option, because I use the JungleDisk encryption. I don’t see a reason to do double encryption.

image

When you create the bucket, you can specify a custom key that encrypts your data. I like this option because I am the only one that has access to the data. Even Amazon can’t tell what I’m storing on there.

image

Performance

Since Amazon is providing the storage, they’re able to scale indefinitely. You can be confident that they can handle whatever you throw at them. They had no problem letting me upload at over 56,000 kbits/sec from my dedicated host. I backed up 4 gigs in about 10 minutes.

Fast Upload

Other Features

  • Bandwidth limiting - If you don’t want to use up all of your upstream or downstream bandwidth, you can limit it, and even schedule when it’s limited. This could be useful for limiting the connection during the day. However, I much prefer a QoS solution since it will maximize the amount of bandwidth I can use.
  • Previous versions - There are extensive options for storing previous versions of changed or deleted files. This option is very impressive, and great for documents.
  • Network drive - You can make a bucket show up as a drive on your computer, which allows you to drag and drop files to and from the bucket.
  • Jungle Disk Plus - For $1/month extra, you can get JungleDisk Plus. They use an Amazon EC2 server to proxy your data to S3. This allows you to resume large file uploads, and also lets you send just the differences. If you’re backing up large files and/or files that may have sections change frequently, this could end up saving you money.