Skip to main content

Part 1: Design and architecture

kino This post will describe the architecture and overall design of Kino. If you haven't already you can download the source from here, play around and tell me what you think.

Architecture

The main purpose of Kino is to serve RSS, and the easiest way of doing this is through a web server. The most modern way of writing web applications in .NET today is through ASP.NET MVC. This is lightweight enough for our purposes, and we will actually not even use but a small part of this frameworks functionality. The project structure will be quite straight forward. We need the web project that is going to serve the RSS flow to web clients, and we need a "library" project to separate presentation from logic (or model, in MVC terms). This is very important and something I do in every project of mine. Logic should be isolated where it can be safely tested, updated and maintained. Last of all we have our test project that where we will put tests for our application. Since this project is such a small project, I'm not going to separate unit tests from integration tests, but keep them in the same assembly. I will not either have a separate test assembly for the web project or the logic library. When we start talking about testing you'll understand why. Kino architecture A common error is that you create one assembly for every single module that is possible to isolate. This is ok to do as a starting point, but you'll have to be prepared to join assemblies later. Lots of assemblies makes the project hard to test, and hard to maintain because of long compile times. Yes, more assemblies actually takes longer to compile than a few. So, isolation of logic is not always good. Most often you can substitute a couple of assemblies with namespaces instead.

Design

One way to design for extensibility is to place a dependency injection framework in the center of your program and let every class that has a dependency go ask the framework for an instance to that dependency. This gives you a highly extensible platform to build on, but it can also make your program very complicated to understand when overused. In our case, we have a very small and simple system. A little bit of added complexity will not do much harm, but you would have to consider the use of your dependency injection tool in a larger system, so you don't reduce complexity through isolation, but increases it through configuration of your DI framework. With that said, the web is connected to the logic through our dependency injection tool Unity. Basic design of Kino The chart above describes the full complexity of Kino. On a web request, the method Index is called on the RssController with a name, representing the RSS feed the client wants to retrieve. The controller does not know how to create the specified feed, but it knows that Unity knows, and therefor it uses the ContainerFactory to retrieve the UnityContainer that could create this RssDocument. When retrieved, it will ask the container to Resolve this unknown dependency and the container will return the RssDocument created. Once done, the RssController will write the contents of that document to the HttpResponse and return it to the client. That is in fully, exactly how Kino works.

Model

We're not quite finished yet. This program is not only extensible because I say it is, but because we really haven't said anything about the RssDocument yet. What is it? As a client we don't really care, because we know that the RssController can retrieve it for us. As an RssController we know what the RssDocument is, but we don't care about how it works as long as we can write the contents to an output stream. Unity knows, and how you configure Unity I will talk about in the next part of this series. So, let us move on to the details of this RssDocument. Class diagram of Kino.Lib.Rss (RssDocument) An RssDocument is really a collection of RssChannels, that are a collection or RssItems. An RssItem could be compared with a blog post and the RssChannel could be the blog. The model is simplicity itself, but to allow dynamic generation of channels, I've included RssChannelGenerators as a parameter to the constructor of RssDocument. Plainly spoken, the RssDocument has a way to generate channels. How channels are generated, the RssDocument does not care about, as long as it gets populated by RssChannels and RssItems. We could pass any implementation of RssChannelGenerator into RssDocument as we would like, but here I've given an example of two generator, RssFileGenerator and RssDirectoryGenerator, that will create RssItems by watching the file system. They inherit from the class RssFileSystemInfoGenerator simply because they have some logic in common.

Extensibility

So, if you wanted to create an RssDocument that took several rss feeds and merged them into one, you would need to create a new RssChannelGenerator and inject it into the RssDocument. If you really wanted to break the rules you could derive from the RssDocument and create your own JSONDocument, and return the result as JSON instead of XML. There is a lot of freedom here and it comes with the price of readability and maintainability. It is hard to get a clear picture of what is going on in a fully independent system, but it is also very powerful. In the next chapter we will go deep into Unity and study the configuration.

comments powered by Disqus