Archive for productivity

A Dependency Injection example with Spring.NET

As requested, here is a real world example of how I used dependency injection to simplify a project, increase modularity, and subsequently increase testability.

Here’s the project. I have a successful website called SimpleTracking.com which allows you to track packages using a simple, common user interface. It also allows you to track pages using RSS.

Here is a list of features:

  • Supports multiple shippers, including FedEx, DHL, and USPS. The tracking number is resolved to one of them, and if a tracking number could belong to more than one, they are called simultaneously, and the one that returns the results is used.
  • Results are cached to avoid overusing the shippers servers
  • Errors are handled appropriately

I boiled the design into a tree of classes:

 image

To greatly simply the design, I decided that each module would implement a common interface. After all, they all take in a tracking number, and return tracking data. Here is the ITracker interface:

public interface ITracker
{
	TrackingData GetTrackingData(string trackingNumber);
}

Simple enough? Every class in the diagram above implements the same interface. If I want to add additional functionality, such as logging for example, I can simply add a class to the chain, and implement the same interface.

Now I can wire it up with Spring.NET:

<object name="postUtility" type="YTech.ShipperInterface.Tracking.Http.PostUtility, YTech.ShipperInterface" />

<!-- The trackers that actually do the work -->
<object name="uspsTracker" type="YTech.ShipperInterface.Usps.Tracking.UspsTracker, YTech.ShipperInterface">
	<constructor-arg ref="postUtility" />
	<!-- Code removed for readability... -->
</object>
<object name="fedexTracker" type="YTech.ShipperInterface.FedEx.Tracking.FedexTracker, YTech.ShipperInterface">
	<constructor-arg ref="postUtility" />
	<!-- Code removed for readability... -->
</object>
<object name="dhlTracker" type="YTech.ShipperInterface.Dhl.Tracking.DhlScreenScrapeTracker, YTech.ShipperInterface">
	<constructor-arg ref="postUtility" />
</object>
<object name="simulationTracker" type="YTech.ShipperInterface.Tracking.Simulation.SimulationTracker, YTech.ShipperInterface" />

<!-- Combine all of the other trackers into one stream -->
<object name="multiTracker" type="YTech.ShipperInterface.Tracking.MultiTracker, YTech.ShipperInterface">
	<constructor-arg>
		<list element-type="YTech.ShipperInterface.Tracking.ITracker, YTech.ShipperInterface">
			<ref object="simulationTracker" />
			<!-- Order these by popularity -->
			<ref object="fedexTracker" />
			<ref object="uspsTracker" />
			<ref object="dhlTracker" />
		</list>
	</constructor-arg>
</object>

<!-- Cache the upstream tracking data -->
<object name="cacheTracker" type="YTech.ShipperInterface.Tracking.CacheTracker, YTech.ShipperInterface">
	<constructor-arg ref="multiTracker" />
</object>

<!-- Handle errors by logging them, and returning a special ErrorTrackingData object -->
<object name="MainTracker" type="YTech.ShipperInterface.Tracking.ErrorHandlerTracker, YTech.ShipperInterface">
	<constructor-arg ref="cacheTracker" />
</object>

Now in my code, this is all I have to do:

var ctx = ContextRegistry.GetContext();
var tracker = (ITracker)ctx.GetObject("MainTracker");
var td = tracker.GetTrackingData("my tracking number");

Every piece I’ve written is fully testable. I even created a class that posts data to a remote web server, and returns the response. This allows me to completely test the tracker classes. They don’t care if they’re hitting against a real server, or an in memory request/response mock class.

I have nearly 100% test coverage, and making changes to the site is a breeze.

The next step is to convert the actual web project to an MVC project so that I can unit test the actual page functionality.

Hopefully I’ve given a good example of how inversion of control can be a really good thing. Have any more questions about the architecture? Feel free to leave a comment.

Note: I haven’t replaced the code on the live SimpleTracking.com site yet, but I plan on upgrading in the next couple of weeks.

What a developer needs from their manager

I’ve a read a lot of articles talking about what it takes to be a good development manager. There are also articles about what makes a good developer. I thought it would be a good idea to describe what a developer needs from their manager.

Thumbs-Up

A developer abstraction layer - There is so much stuff that goes on in a company, and I really don’t need to know it all. For my own curiosity, give me general interesting tidbits, but more isn’t necessary.

Leave me alone - If you interrupt me for no reason while I’m getting a lot of work done, I’ll obviously get less done. It’s not worth interrupting me just to find out what I’m doing. If I’m walking around, that’s probably the best time to talk to me.

Buy any training materials that I request - Books are cheap compared to my salary. If I can learn something new that will save time, the investment will have been worth it. The same goes for magazines, software conferences, etc.

Be flexible - When it’s time to get some coding done, there are times that I’ll be more productive than others. My computer doesn’t care if I’m using it at 3AM or 10AM. You shouldn’t either.

Trust - If you don’t trust me, you’re setting me up for failure. Trust your employees first, and take appropriate action if they give you reason not to trust them. If I know you trust me, I can focus on getting my job done.

Keep me happy - A happy developer is a productive developer. Sometimes there are small things you can do that will keep me happy. Buy lunch every once and a while. Tell me to go home early on a Friday. As a bonus, I won’t be looking for another place to work if I’m happy.

Guide, but don’t over-manage - You have the big picture, so I need your guidance. That doesn’t mean that you have to know every detail about what I’m doing. You’re not a babysitter, you’re a teammate.

Be accessible - If I get need something, please be available. I may need you to pull in the right resources to solve a problem.

Have answers - You’re the hub of the wheel. If you don’t know what’s going on, you’re useless to me. You need to be organized and connected.

Be able to prioritize - You have a better idea of what is important for the overall product. That means I need you to prioritize features accordingly. That means I’ll always be working on something important.

Tell me what is expected of me - I need to know exactly what is expected of me, and I need to know how you’ll determine if I’m completing what is expected. I also need to know how you’re going to gauge my performance. When it’s time for my review, there should be no surprises.

If you’re interested in more information on this topic, I highly recommend you read "First, Break all the Rules - What the world’s greatest managers do differently". It’s not specific to development managers, but it certainly applies. In that book, they empirically determined the factors that are the most important traits that promote success and happiness:

image

  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?

That book is one of my favorites, and I highly recommend all managers read it.

Are there any other factors you feel are important? Leave a comment and let me know!

I finally get the point of inversion of control

I think I’m finally starting to understand the Inversion of Control principle (aka Dependency Injection). I had a hard time understanding most examples out there, because they appeared to be solving problems that didn’t even seem like real problems to me. For years I’ve been writing classes, testing them, and hooking them together. In many cases, I was already practicing inversion of control. The benefit I wasn’t seeing was the fact that you can separate the modules in your code and the connections between them.

traditional-vs-di

When you really commit yourself to breaking the problem down into manageable pieces, it does create more testable and reusable code. I already knew that, but when you starting using IoC, it really starts to drive that point across. It’s similar to the effect that unit testing has. When you start writing unit tests, you try to make your classes more unit testable. When you start using a dependency injection framework, you try to make your classes more open to injection.

So what is a dependency injection framework? It’s the glue that holds your pieces together. Without it, your classes would probably be dictating the classes that it depends on. With dependency injection, the application configuration tells the class what modules to use. A dependency injection framework separates the linking from the pieces.

ioc diagrams 

In the diagram on the left, it’s a typical tightly coupled design. Every class is hooked up directly to another class. This doesn’t mean that each class isn’t testable, but it’s a very rigid design (which isn’t necessarily avoidable). In general, the easiest unit testing was in the classes on the edges, since they have a usable surface area.

The diagram on the right is closer to what I’ve been creating while using a dependency injection framework. In the first pass, I create pieces that contain my business logic. Then, I can use the dependency injection framework to declaratively define how those pieces are wired together.

At this point, I would have a hard time NOT using something like this. While this concept isn’t new, the frameworks have recently become very mature. Personally, I’m using Spring.NET and loving it. One of my pet projects for package tracking,(SimpleTracking.com) has been rewritten using a modular, test first, dependency injected design philosophy. I was able to reduce the amount of actual code by quite a bit, increase my testing coverage, and decrease the amount of duplicate code.

Sold

I’m sold!

Improve your software by creating an API

I’m going to talk about the benefits of having an API for your product, and why you should consider building one for your next project.

I used to work for company that developed manufacturing software. Now I’m on the other side of the fence. Since I work in the IT department, I’m asked to help in evaluating the software that our company will use. One of our main tasks is to write the glue that puts all of the other pieces together. We know we’ll have to fill in the gaps with custom software, since no boxed software is perfect for our custom process. Those gaps could be missing functionality, or it could be code that hooks up two systems so that they work together.

So what is the single best thing you can do to help people like me out?

Have an API for your software!

Doorway

If your software has an API that lets us read and write the valuable data in your system, it’s going to save us a lot of time. If we have to start modifying data in your database, we have to worry about tables changing. Worse yet, you might be using a type of database that we’re not familiar with. That’s only going to make us less likely to upgrade.

The great part is that this makes your software easy to sell. If someone asks for a feature that you don’t have, you can tell them that your great API supports it, and their IT team could easily build that custom functionality. Better yet, they may contract you to build it for them. You can avoid saying "no", which can sometimes be the kiss of death for a potential sale.

What else can you do to have a great API?

  • Try to avoid being restrictive on how the data is queried. The Flickr API is a great example of allowing full access to just about everything, and allowing it to be queried in an amazing number of ways.
  • Try to maintain backwards compatibility when possible
  • When necessary changes are made, have a list so that our software can be updated
  • Have great documentation, which some clear examples

If you want to make sure that your API can truly get at all the data a customer would want, then why don’t use use it yourself? If your own product is built on your API, it will be another selling point, as well as a guarantee that it fulfills the need. It also ensures that the layers in your software are not blurred. You will have a clear, well defined way that all data is moved in and out of the system.

Software is hard!

Not too long ago, I was telling my uncle about an e-commerce site that a coworker and I were able to develop in about 4 months. I was shocked at his next query:

What is so hard about that? Why did it take so long?

What??? I write thousands of lines of code over dozens of pages, and you don’t get it? In a way, that means the software was successful. Often, the simpler the end result, the more code it takes to achieve that simplicity. Most users are completely oblivious to what it takes to create something that actually works.

 Frustrated Developer

Windows has over 50 million lines of code, which was written by over 5000 developers. I’ve heard that NASA spends over $10,000 per line of production code.

So why IS software so hard? It usually requires the entire mental ability of a software developer. In a given day, one would surely exercise their entire brain.

To write a feature, here is just a fraction of what must be considered:

  • Software creation is art and science. You must be creative, imaginative, logical, talented, and knowledgeable.
  • Layer synchronization - Data gets passed up and down between layers, and they all need to agree on how they will call other functionality, as well as how they need to be called. Decisions need also be made to determine if and where data will be validated.
  • Failure modes must be considered - For every line of code, there needs to plan to handle that failure.
  • Affected code needs to be evaluated - Ever heard the line "this is a small change, it won’t break anything". I’m not falling for that one again. It’s like changing out a block at the base of a pyramid.
  • A testing strategy needs to be formulated - Unit tests need to test the new code, and acceptance tests need to test the new functionality
  • More code must be maintained - Every line of code you write counts toward the theoretical maximum number of lines of code that you can realistically maintain.
  • Consider performance and memory - The questions in this area are virtually endless, and the answers might not come easy. Compromise is inevitable.
  • Technology considerations - How much does the target platform vary? What technologies will work, and which ones are the best?
  • Balance modularity and simplicity - Sometimes they go hand in hand, sometimes they’re a tradeoff.
  • Balance the needs of the present with the needs of the future - Try not to play the "What If?" game, but at the same time, don’t be ignorant of the future.
  • Many companies have cross functional teams that developers must report to. Instead of having a manager that feeds a developer their work, now you have multiple sources that are asking for conflicting information. So much for a developer abstraction layer.
  • You’re not the only developer - You need to be cooperative and collaborative to simplify the integration of your code.

Nothing is ever as simple as it seems. You’re not going to piece together code snippets from the web and create a great product.