Archive for productivity

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.

Don’t play the "What If" game

One of the biggest traps I’ve seen developers fall into is what I like to call the "What If" game:

  • "Make your ID columns integers", "But what if we want them to contain a letter eventually?
  • "Let’s cook these 10 steaks", "But what if 100 people show up?"
  • "Let’s go to the park", "What if we get sick?"

The "what if" game consists of over thinking your plan. Planning in general is obviously essential. However, I’ve seen an alarming rate of crippling fear. Fear to write any code because it will never possibly handle all possible scenarios. It ends up being a self fulfilling prophecy of failure.

Sometimes the side effect isn’t just a fear to write code. It often leads to code that is generic beyond usefulness. For example, a database with all columns being VARCHAR(MAX).

Specialization is basically a spectrum. At one end, we have code that is so specialized that it is basically un-reusable. At the other end, the end I’m talking about, we have code that can be used everywhere, but doesn’t really do anything.

Some of the hardest decisions we have to make as developers are related to whether we base our decisions on the present, or a potential future that has a variable amount of certainty.

I’m not saying that you should avoid planning, but your decisions need to be based on the real likelihood that changes will need to be made later. An ounce of prevention is worth a pound of cure, but 64 ounces of prevention is certainly not worth a pound of cure!

When should you use database constraints?

A discussion came up at work recently about the extent of constraint usage in your databases. There were basically 2 camps:

  1. Constrain everything humanly possible. If it’s an integer that wouldn’t normally be negative, add a ">= 0" constraint.
  2. Constrain primarily where it’s necessary to maintain referential integrity.

Consider the following diagram. It’s a map of the flow of data from your user, which eventually makes its way into the database.

Validation Layers 

Since we’re getting input from a user, and they’re the one that can fix invalid data, we validate data at the top layer. There’s usually no getting around this. In fact, for the best user experience on the web, you’re going to perform some JavaScript validation. Then you’ll probably validate it again on the server, in case they have JavaScript disabled.

At this point, unless there is a bug in your code, you’re sure that the data is valid. You may not know if it’s referentially valid. Validating the input a third time in the database is probably overkill. It’s also a potential performance bottleneck.

Yes, there are many times when this doesn’t apply. For example, when multiple systems are interacting with the same database, and one counts on the data in a certain format. The only way to guarantee you get data in a format you expect is to constrain it at the database level.

In general, I avoid strict constraints at the database level. The biggest reason is that it requires your to synchronize all of your validators. They all have to agree on the same set of restrictions, or the code will fail. That goes against the LEAN and Agile philosophies. When I want to allow negative numbers in my integer field, it’s much easier to simply change it in my application. This is amplified if you have to talk to a DBA to make changes.

Another reason to avoid constraints is that they can’t always understand the data like the application can. For example, should a constraint attempt to ensure that valid email addresses are entered? If you’re storing a persons age, do you constrain it so that it can’t go above 500? 200? 100?

iStock_000005716223XSmall

Now let’s assume that there is a bug in your application code, and you didn’t have a trusty constraint to stop it. You now have invalid data in your database. The good news is that you now have the potential to clean it up, or adapt your code to deal with it. The bad news is that if that value is used in a calculation that could have bad side effects, you could have big problems.

As with anything, there is no hard and fast rule for every situation, but we can at least make some general guidelines.

Think LEAN. Anything that doesn’t provide value to the customer is waste. Think Agile, requirements change, be adaptable.