Friday, July 10, 2009

New technology - If you don't adopt are you untrendy?

I could have called this "The anti-pattern of choosing new technology" but decided against it in the end.

That probably gives you readers and idea of what I'm talking about in this post.

There are a lot of questions that I read that go something along the lines of "If I choose technology x, how would I make it work with the following scenario...". Spot the obvious mistake there?

The architecture always comes first, then start simple, and work to the more complex, or unknown solution, as requirements discount the most simple ideas.

If more architects of systems thought like that, certainly a lot of the work I have done over the years would not have been necessary. Somebody believed that a particular technology did something in a particular way, pushed it a little harder, and found that they were too far down the implementation to pull back, as the technology no longer fitted the requirements at all.

A case in point, and the forums are flooded with questions surrounding it - is LINQ. Don't get me wrong, I have nothing against the technology at all, it is great, in the right place. Honestly though, unless you have a very good justification for using it, it's quite probable that the old data reader / data adapter and sprocs is going to be a simpler and more understandable solution.

My problem with the technology is that it uses some logic to try to get the best performance out of a query - it's good, but I'm afraid, it isn't as good as me. What I mean there is that you have little control over how a statement gets implemented, so how can you possibly tune it? That for LINQ to do, right? So long as it does, that is fine.

So if you're starting out designing applications, take a bit of advice, and keep it simple, understand the technology fully before using it in big commercial applications where it ends up needing o be worked around.

Separation of Concerns

Here's the thing - recently I put together some questions to use for interviewing, and one of the questions on there was simply what was "separation of concerns".

None of my team got that question right, although some of them are quite experienced, but all of them told me that this was a dated question that will only invite a textbook answer.

The point here is that a good design has good separation of concerns, and is coherent, but what does that mean? Simply put, a subsystem with a particular responsibility performs only that set of tasks, and no tasks for other subsystems. It's a little like the normalisation rules for databases, that the key must refer to all the data in a table.

This poses a couple of immediate questions, what happens when you have a Person subsystem, and want to get the addresses that that person resides at, without making a chatty set of calls?

There are a few approaches - if we're talking services, then the service call is very granular, and uses a DTO in effect to transport data from multiple sources. In the backend, the multiple source are nicely separate.

If the problem is considered from the backend, the Address subsystem would have to be injected into the Person subsystem, and vice versa. In this way you are delegating responsibility to the correct subsystem, however, this could lead to many calls to the database. Do we care? Well, we might do if the data really does have to be realtime, which is wouldn't in the given example above.

The final implementation would be to implement functionality (a PersonAddress nested subsystem within Person subsystem) or an AddressPerson nested within the Address subsystem. These would have a very different focus, or context, but the code is quite likely to be repeated in both. I guess that final point is similar again to the database example, in that generally you should start with 5th normal form, then work backwards to compromise redundancy against speed. Same with coherence, but it is "separation of concerns" versus maintainability.

Decoupled design

Okay, so the question got asked on the Microsoft Forums about what was most appropriate, an interface, or an abstract class, so I thought that I'd bring that discussion over here for further discussion.

My response was to decouple, you would definitely use an Interface.

I was responded to with the question, but doesn't Inversion of Control containers now take care of abstraction, of de-coupling. I have to agree that it quite probably does.

That got me thinking, if you did use inversion of control, and always used abstract classes with no implementation, you would effectively have an interface. So why not use abstract classes everywhere? For me, it all comes down to clarity - the naming of an interface means that it is easy to understand it's function. An abstract class, on the other hand could be something ranging from effectively the interfacing class as described above, to something with lots of references to other abstract classes.

This is where I stand firm - my definition would be correct, if only to prevent that very thing from happening. When the implementation is part of a big team, those sorts of things can easily creep in, and before you know it, that beautiful, loosely coupled architecture is now reduced to a monolith.

So my advice here is always use interfaces, if you need an abstract class, create one, but only ever reference it using the interface. This bit here is another place where it is nice to have an interface - what if the base implementation changes? You can still create another base implementation class, and so long as the contract is unchanging, only that need change.

Coupling of code is all about the coupling of implementation from one to another - the very thing you have to avoid with SOA implementations and the like. The service call must be completely encapsulated.