April 2005 - Posts
In my last posting I drilled down into the details of a Software Cells. We looked at the substructures of the Core, the Adapters and the Portals. But altough I think, those substructures make much sense and should be taken as a guidance when designing an Application, I´m very open for deviations and different ideas. Should a User Portal always implement the MVC pattern? I´d say, yes, try to map your problem to MVC, start out with MVC - but if it does not match your specific problem, then do the User Portal some other way. Most important is to see the User Portal as a separate entity from Core, Adapters and Application Portal. The same goes for other structures of a Software Cell.
Now, if the substructures are merely recommendations (or even "best practices"), why stick to the structures anyway? Why mandate a Core and differentiate Adapters and Portals? Because to have them means to separate responsibilities within an Application. Current software development lacks a strict (!) recipe to structure a Solution. Software layers are just a logical model for software. They leave it up to you how to split a Solution up into Applications and Applications into components. The Software Cells model on the other hand very cleary states:
- A Solution consists of one or more Applications. The exact number you´ve to find out by analysing your problem and designing a Solution.
- An Application has at least two physically separate parts: a Host EXE and a Core DLL. Mostly the Host will be prefab so you just have to choose an appropriate one. The Core, though, is your minimum responsibility to develop.
- Since an Application with just a Core and no way to interact with the environment is rarely of any real world use ;-) you need more in your Application. You need means to interact with the Application´s environment. So a real world Application needs at least one Portal or Adapter, since it needs to be able to access other applications/resources to read and/or write data. Since the inception of software it was all about IO. In German we even link it to the beginning of (christian) time ;-) and call this basic principle EVA for Eingabe-Verarbeitung-Ausgabe which stands for Input-Processing-Output. So the basic demand of Software Cells is: Think about your IO explicitly and separate it from the domain logic of your Solution. Then Software Cells go beyond this obvious principle and categorize IO. They say, you should differentiate between IO with a user, IO with resources with comparatively low level APIs and communication partners with high level APIs (i.e. other Applications).
That´s to summarize what I´ve described so far in my postings. Now, today I want to add two more very clear statements to this list:
- Software Cell structures define their services using explicit contracts.
- If a Software Cell offers a service to other Software Cells, then this service is described by an explicit contract.
If you view a Software Cell as a service as in SOA then the last statement should come at no surprise to you. Software Cells fully embrace the SOA tenets and want to help you architecting SOA solutions.
But since Software Cells see solutions as distinct physical units and consisting of physical entities they carry the Contract First idea into the realm of "ordinary" software development. This, too, is not new - emphasizing the importance of separating interfaces from implementation is at least as old as the Modula language let alone Corba´s IDL and COM´s reliance on interfaces -, but it has been neglected in the past years. The .NET Framework has made deployment of multi-DLL programs so easy, it seemed less important to design clear interfaces first.
But if you really want to realize the benefits of component oriented programming (COP) and modularization, then clear and explicit interfaces are as important as they were 20 years ago. To make this plausible think about this for a moment:
In SOA each service is an autonomous entity. But not only at runtime! Also at design time it is treated as a separate unit of development. Ususally its development is even not under your control. It is developed by some other party you can´t even influence. You don´t know (and you are not supposed to know) any details of its implementation. And I´d even say, you should be glad about it! It relieves you from thinking about details that don´t matter to the solution of your own problem. You treat another service as a black box and just see its published interfaces. That´s it. So easy! Focus on your own task and just see to that you use the service´s interfaces correctly.
Likewise it is very prudent to see your Solution and within it a single Application as a set of "services" or black boxes. From the point of view of one Application in your Solution other Applications should be opaque. No details are visible - except for their published interfaces. Likewise within a single Application the Core should view Adapters as black boxes, and Portals should see the Core as a black box.
And to go even further, each component within one of those structures should see other components as black boxes. To add to the common definition of components as separately versionable and deployable entities Software Cells state, a piece of software can only be considered a component if it draws an explicit boundary around itself. A component needs to publish its services thru interfaces. Only what is defined by a component's explicit interfaces can be accessed from the outside.
Components thus are physical entities of isolation at design time as well as runtime. To use a component means to program against its interfaces. It means, at design time you don´t even know the implementation of those interfaces. The component your code will use during runtime might not even exist while you´re developing it. So your component cannot bind statically to the other component. Only by decoupling components in such a strict way true independece can be reached. And only if components are so independent of one another they can truely be developed in parallel.
This is what happens per definitionem in SOA. And this is what should be done in each and every application.
If you want to reach higher productivity for your team, you can either scale up or scale out. Scaling up would mean to make each developer more productive. Maybe you can teach him/her to type and think faster. Maybe you give him/her a better development tool. But in the end you´ll always reach the limit of what an average developer with the best tools you can afford can accomplish.
To scale out your development, though, means to add programmers to your software project. But not late in the process, because we know, that makes it later ;-) Rather you can do it proactively early on during the project. Nobody needs to wait to start developing the Core of an Application. Since its interfaces as well as the Adapters´ interfaces are defined, Core development can start at the same time as Adapter and Portal development. Even developing Core components can start in parallel - if you´ve the manpower.
But explicit interfaces within a Solution or Application don´t only decouple components from one another and make parallel development possible or at least easier, they also provide very valuable endpoints for automatic testing. And that sure helps to improve the quality of your Solution.
Now, after my pleadings for Contract First design within Software Cells, lets have a quick look at where those Constracts are located.
There are at least two categories of Contracts in each appliction:
- Contracts defined by the the Core to regulate access from Portals.
- Contracts defined by Adapters to regulate access from the Core.
In general, a contract needs to be defined whereever there is a Component (i.e. functionality you want to isolate):
The Contract describes the operations that can be called, the data that is passed to and fro, and the events the component can fire to notify callers asynchronously.
The outside world can access a Software Cells thru the sum of its Portals´ Contracts. Application Portals define formal contracts, but User Portals don´t. User Portal Contracts consist of the user accessible frontend controls (e.g. dialogs, buttons, menu items).
Intra-Application Contracts are defined using the CTS. They only contain interfaces! No class definitions, not even abstract classes should be used in Contracts. (Abstract classes, even though, they don´t contain statements, are a form of implementation code. The force both the caller and the implementor of a component into a class hierarchy.)
Inter-Application Contracts should be defined using WSDL and XML Schema to make Applications independent of their implementation technologies. However, within a Solution, that means among several Applications solving the same problem, and being implemented by the same team, this requiredment can be loosened. As long as an Application is only called by other Applications from the same solution and (!) both interacting partners are implemented using the .NET Framework, a CTS based Contract definition is ok, I´d say. It´s easier to write and understand, and it can later be converted automatically to WSDL/XML Schema, if need be.
However, Inter-Solutoin Contracts should without exception be defined using WSDL and XML Schema.
Defining Contracts first, when designing an Solution with its Applications is core to Software Cells. Without explicit Contracts there is no real decoupling. (Why should a Core know how another Application is accessed? Why should it care about the transport technology used?) Without decoupling there is no real componet orientation. Without component orientation there is no highly productive parallel development. Without real separation of responsibilities among teams there is no feeling for responsibility to test "your own shit" ;-)
Now, where are we? Customer problems are solved by developing Software Solutions. Software Solutions consist of Applications which can be described as Software Cells. At their heart is some sub-problem solving Core-functionality. Around the Core exist Adapters and Portals to connect the Core to the outside world, i.e. to other Applications within and outside the Solution and to the user. All structures of an Application run within a Host and consist of Components. Components are black boxes whose services are described by Contracts. To use the services of another Component code only binds to the Component´s contract (interface), but never to its implementation (a concrete assembly). Which actual implementation fulfills service requests according to the interface is only resolved at runtime. Contract implementations thus are dynamically bound to emphasize decoupling and allow for real parallel development.
Ok, so much for Contracts.
But what about communication between Software Cells? What about the inter cellular space? What about SOA? Watch out for my next posting ;-)
Now that I have explained the basic structure of Software Cells I need to drill down into the details of its structures. What´s the design of a Core, of Adapters and Portals?
Let´s start with the central piece of every Software Cell, the Core. The Core´s task is to solve a problem, e.g. calculate the digits of Pi, manage invoices, edit bitmaps, or compile computer language source code. Whatever the purpose of your application is, there Core is the one to control everything towards your satisfaction. There is no Application without a core. But there are Applications without Adapters or Portals.
Since the Core is the workhorse of an Application it sure should not be implemented as one piece. Right to the contrary! You should modularize it as much as possible. So a Core can look like this:
It consists of several components. (For now lets leave any "priorization" out of the picture.) They work together to solve the Application´s problem. But they are not concerned with direct data access or user interaction or application interop. That´s all the task of adapters and portals.
Since user interfaces traditionally are so at the center of application development, let´s look at the User Portal next.
As you might have guessed, a User Portal implements the MVC pattern. It can contain many views and controllers and models. Most important to note is, the controller manages the access to the Core. (In simple scenarios, a single WinForms form might implement view and controller at the same time.) The user interacts with the view (e.g. by pressing a button or seeing a chart), which reports any user interaction to the controller thru events.
The other path from the outside to the Core is thru an Application Portal. It allows other applications to access Core functionality.
To fulfill this task, an Application Portal needs at least a facade, i.e. an entrypoint into the application with a published interface other applications can connect to. Although the facade is called facade it needs not necessarily be a class callabled via SOAP. The facade could be a TcpListener/TcpClient combination implementing some network protocol (e.g. FTP or homegrown). If an Application Portal needs more substructures before a call to the Application reaches the Core depends on the type of Portal, operations and messages.
The Application Adapter works the other way round: it lets the Core access another application.
The low level access is done thru a proxy (like a Web service proxy generated from a WSDL document). But a Core should make itself not dependent on an interface description it might not control. (Think of a WSDL document published by some service offering on the Internet. You never know when and if and what way this WSDL will change.) Rather the Application Adapter should contain a layer called "High Level Application Access" shielding the Core from the details of accessing another application.
Finally the Resource Adapter should follow the same pattern:
The Core does not know about the details of accessing a resource. It wants to see a high level interface of it. That´s provided by the High Level Resource Access layer (HHRAL) of the Resource Adapter. At the other end is the resource´s API. And in between might sit a Low Level Resource Access layer to unify different APIs for the HHRAL, e.g. a generic ADO.NET managed provider to level out differences between database products.
You see, a Software Cell is not just a shape with a blob in it, but consists of a rich set of structures and substructures. The Core has the responsibility to solve a problem, and Adapters and Portals connect it to the outside world, since information processing still is about input/output.
The main purpose of the substructures of Adapters and Portals is to bridge the impedance mismatch between the outside world and the core, as well as isolate it from changes happening out there. At the basis of Adapters lies an API (either a dedicated API like ADO.NET or a automatically generated one like a Web service proxy (which again is based on System.Net)).
Since Adapters are layered, now you might ask, why I think Software Cells are a valuable concept? Well, my answer is, the well known layer model has two flaws.
1. It is only concerned with logical concepts. There is no connection to the implementation of an application, i.e. to assemblies or hosts. In addition I find the layer model imprecise in its use of the term "application".
2. The layer model seems so easy to understand, because we are used to the 7 layer OSI model for network communication. But there is a fundamental difference between the two: OSI layers raise the abstraction level one by one - but the fundamental task of each layer is the same: transport information from A to B. In the layer model, though, the abstraction level does not (necessarily) rise from layer to layer. Instead the tasks of the layers differ fundamentally (one layer is concerned with accessing a resource, one with complex algorithms, another one with presenting information). To depict such fundamentally different things as layers, I think, is contraproductive. I makes it harder than necessary to understand what layers are, which functionality to put into each layer, how to design their interaction.
Software Cells try to overcome the limitations of the layer model. They integrate logical concepts (e.g. Adapter, Portal) with physical artifacts like a Host. They precisely describe what an application is, and what "distributed application" means. And they still allow you to model the traditional layers - either within an Application or as a system of Applications.
And finally in Software Cells the different tasks are depicted differently. Also, whether the abstraction level is equal among the structures is not of any concern. Different responsibilities are assigned to different parts without any suggestion of a "priority".
So where are we now? We know the structures and substructures of a Software Cell. But we don´t know how they interact. And we don´t know how Software Cells interact. That will be the topic of my next posting on Software Cells.
In my last posting I introduced the term Software Cell to describe a software application. The minimally necessary ingrediences - a Host and my code to solve a problem (logic) - just looked like an organic cell once I drew some pictures of applications consisting of a Host EXE that contains some assemblies.
In this posting I want to drill down into the details of a software cell. Like organic cells it has a structure: A software cell has to deal with the outside world and I find it benefical to extract the necessary functionality for communication from the core. It´s a separation of concerns.
If an application is not selfsufficient but needs to get information from the outside world - or serves other applications as an information source -, then it needs structures to connect with or to be connected thru.
There are two categories of basic communication structures: Adapters and Portals.
Adapters reach out to other information sources/sinks, and adapt their interfaces to the needs of the core. The Core does not want to concern itself with the details of communication. It wants to live in its world of domain concepts and is shielded from the rough outside world by the adapters, who translate its requests to whatever the communication partners require.
Since there exist at least two general kinds of information sinks/sources, they are matched by two kinds of adapters:
A Resource Adapter connects to a "low level" data resource like a database or a FTP server or the file system. The abstraction level of the resource´s API is low compared to the level of the Core, there is quite an impedance mismatch to overcome. A Resource Adapter thus needs to do some "heavy lifting" in terms of adapting the low level data structures/operations of the resource (e.g. tables, rows or lines in text files) to the needs of the Core (e.g. Customer objects, SMS messages). (Although I used the common database barrell as a picture for a resource it´s perfectly ok to think of a resource as an application of itself. Unless however I write code to be hosted in the resource´s Host, I would not draw a triangle for it.)
An Application Adapter on the other hand connects to another application by a much higher level interface. Whether that´s a Web service or some other means is not important, though. The distinguishing characteristic of an Application Adapter as opposed to a Resource Adapter is the smaller (or even non-existing) impedance mismatch between the data model of the communication partner and the Core. If an Adapter does not need to do "heavy lifting" in order to connect the application to the outside world, I consider it an Application Adapter.
With both adapters the control flows from Core to the outside world.
Each Software Cell can contain an arbitrary number of adapters of both kinds.
If the outside world wants to use services of the Core, however, it needs to go through an Application Portal. The portal provides an interface of some kind thru which operations can be initiated and data can passed to the application. Control flow is from the outside into the application. Whether the portal is implemented as a SOAP Web service or as a custom protocol on top of TCP/IP is not important. The portal just defines some communication endpoint to connect to.
Of course each Software Cell can contain an arbitrary number of portals.
Now, after code for communication has been extracted from the core, what remains in the Core? The Core contains only code necessary for solving the problem. Call this logic or domain logic or business logic or whatever. For calculating prime numbers this could be just one method implementing Erathostenes´ sieve. That´s all. But it also could be many assemblies all working in concert to do some complex data analysis. The Core´s task is to do the problem solving, nothing more, nothing less. And when it needs to access outside information, it uses adapters. In turn, if the Core´s work is to help other applications, it is sent requests thru a portal.
For me it´s very important to distinguish the Core´s functionality from data access and data presentation. In essence, an applicaton should be able to do it´s work without any user interface. (Yes, even a highly visual game.) My recommendation is to design the "blind" Core of an application first without thinking of specific presentation requirements and the details of information access. Later on you can worry about all that, but don´t let uncertainities about a datagrid or database API distract you from your real business: solving a domain problem. Adapters, portals and even the user interface thus are more or less "infrastructure". And we all don´t want to waste too much time working on infrastructure; we´ve more important things to do ;-) (Yes, I know somebody has to position those text boxes and read the data from the database. I´m just trying to say, most of the time that´s not really the important stuff.)
Since I have mentioned the user interface what about it? Where does it fit into the Software Cell picture? I think, it should be another structure within the Cell:
The user interface is implemented by the User Portal. The User Portal is a portal, because again, control is flowing towards the core. The user controls the operations of the core by clicking buttons and menu items and entering data. But since it´s a less uni-directional communication than thru an Application Portal and (often) has to do with visualization, I used a pentagon as the shape for the User Portal to distinguish it from the Application Portal.
To finish off let me show you a couple of drawings for common Solutions:
(Please excuse me leaving the little lines with arrows out for the moment. I guess the informaiton flow is obvious.)
To me these little drawings are quite easy to understand. The clearly show the boundaries of each application and they show how much work has to go into "communication infrastructure" in each application, i.e. which adapters and portals are needed.
What´s left now? We need to talk about the substructures of adapters and portals. We need to talk about interfaces. And we need to talk about the "inter software celluar space". And, yes, I guess I need to say a couple of words about why I think this kind of model is valuable even though we have layered architectures and onions and fiefdoms.
If you´re still sceptical and don´t believe the proposed definition of software applications as a combination of a host plus my problem solving code has any merit over the so far diffuse usage of the term "application", maybe I can convince you to rethink your position with a couple of pictures?
I think, once we are able to clearly delineate an application in the proposed way, we can start drawing pictures of software solutions in a new way. Let´s start with a single application:
I think, this is a simple picture and it is easy to understand. It does not imply much. There is just host and my assemblies. I think, all of your applications look like this, with one distinction: Except for when you develop an ASP.NET solution or a ServicedComponent, your Host is an assembly containing some custom logic specific to the solution you develop. But let that not stand in our way for the moment.
First let me make the picture even easier, let me replace the curved outline of the host:
I chose the simplest 2D shape to depict the host and put the custom assemblies right in the center in an opaque shape so we don´t get disturbed by to many details right now.
What we get is a Host with a custom code core at its center. The purpose of the core is to solve some problem, the purpose of the Host is to provide a convenient environment for the core to do its work.
Now let expand our picture: As you know, I think of the combination SQL Server + stored procs as a separate application. Then this is the simplied picture of a C/S solution consisting of two applications:
If we leave out the question how those applications communicate with one another, I´d say, this is a pretty simple picture: Two applications that belong together to form a solution. Their vicinity very naturally suggests a cooperation between the two. No statement is made and does not have to be made at this point about where those applications are deployed. They might run on the same machine or on different machines. But by distributing our code which solves a problem across two applications we know there is some gap between the distributed parts. Very likely this gap is expensive to bridge and needs special consideration.
But let´s move on to more complicated scenarios. How about a WinForms application (frontend) calling a Web service which functions as a facade for a COM+ component which in turn uses stored procedures in the backend?
I just needed to add a couple of triangles/Hosts and need not worry about the details of their cores.
I was just concerned with how the applications communicate with one another. But an intuitive premise of this kind of picture is: information flows between applications where they border on one another. That means, I could have drawn the picture also like follows to resemble the common 3 layered architectures:
You see, my definition of applications so far nicely complements our beloved application layer architecture model.
But before I dig any further into this new picture or model for application design - there a many details to flesh out -, let me give it a name.
Let me call those little triangles with the black core Software Cells, because putting many applications next to each other - e.g. in a large SOA picture - looks like a united cell structure from a biology text book, e.g.
Each application for me thus is a software cell. The exact form does not really matter. A triangle is just the simplest 2D shape; so if you like, use squares, octagons or whatever you like to depict the outline of your application, to give it a surface other software cells can connect to. You can even go 3D: use a tetraeder or cube. Each edge or surface, though, should connect only two software cells/applications.
Also it´s ok, if you find regular shapes limiting to depict larger solutions consisting of many applications. A complex network of applications might need an n-dimensional space to connect all those software cells thru adjacency. But that´s hard to draw on a piece of paper :-) So what I suggest for complex networks is to view software cells not as simple onion cells (see 2nd picture above), but as nerve cells:
Nerve cells reach out to other cells near and far. So can software cells. (Interestingly, the communication between nervce cells across synapses can be thought of a form of marshalling: electrical impulses have to be"serialized" into chemical messages (!) to cross the gap between two nervce cells.)
But more of that in an future posting.
Somehow I cannot publish two comments I received for my proposal for a stricted definition of the term "application", so I´m publishing them this way with my comments:
Mujtaba Syed wrote "Have you heard of this 'indirect' definition: 'There is only one application. And it's still being written.'" I have to admit, I haven´t heard about this definition - and I don´t see any value in it. This definition does not attribute any use to the term "application". Because if either the one (and only) application is all code being written or it is developed at some unknown place, it is irrelevant to us. Yet in my day to day life developers and customers alike are talking about "applications" all the time, so "applications" are real and relevant to them - although they might mean different things when they use the term. Unfortunately I have to say, Mujtaba´s definition makes even more obviuous the fundamental problem I yesterday felt exists: there is no clear definition of what an "application" is.
John Cavnar-Johnson then replied to me with "I think you're going down the wrong track here. Are you familiar with Aristotle's four causes? I would argue that you're making the mistake of assuming that you can define an application based on its constituent parts. If, instead of an application, I asked you, "What is a statue?" would you say it's bronze? No, a statue can be made of bronze or marble or any number of materials. A statue is a statue because the artist is using the material at hand to represent something else. A statue is defined by its purpose.
Likewise, an application is not defined by the programming artifacts we use to create it. Instead, it's defined by the users' requirements. An application is a collection of software, hardware, and other artifacts that allow users to accomplish a goal. You may be satisfied with your description, but it's fundamentally wrong." I like John´s reply because he tries to find a sound fundament for his argument, that my definition is wrong. However, it´s sad John does not provide a better definition of "application" either.
Now, however, after some thinking I don´t agree with John: Aristotle defined 4 causes for everything being:
- causa materialis: the material something is made from.
- causa formalis: the form/shape of a being.
- causa efficiens: the causing agent.
- causa finalis: the purpose.
Applying these causes to software applications (or short: applications) according to my definition is esay, I´d say: applications are made of IL-code (causa materialis). This code is shaped into assemblies with ever differing interfaces, each application has its own assemblies which look different from those of other assemblies. Some may be the same (e.g. 3rd party controls or the host), but most of them are individually crafted. In total they define the shape of an application (causa formalis). The team developing those assemblies are the causa effciens. And the purpose of the application is to solve a customer´s/user´s problem, e.g. writing an invoice (causa finalis).
Since "my" applications can be described very precisely in the line of Aristotle´s thinking I feel my definition is useful. It is able to describe a being.
So where John sees me erring fundamentally I on the other hand feel supported by the ancient authority he mentions. And I´d like to ask John in return: Why can´t I define a thing by enumerating it´s attributes? A knife is the combination of handle and blade fitting in my hand. Blade and handle can take all sorts of shapes and can be made of many different materials. Its purpose is "cutting" (at least mostly). If the handle-blade combination exeeds a certain size it becomes a sword. And I´d say I recognize a knife when I see one, I can distinguish it from a spoon or sword or lance.
Likewise with my definition I can recognize a software application when I see one: When you show me a host-my code combination I can point at it and say "application". (Which other definition of "application" make it as easy to say "This or that exactly is the application."?) And when you are talking of your application I can ask specific questions, like "What is the host of your application?" or "Where does your application run?". Especially the latter question could not be asked without a precise definition of "appliation".
Being able to ask precise questions and categorize beings and delineate them is the purpose of definitions. That´s what I think my proposal for "application" achieves.
If I left out the "purpose" of an application for a moment, please excuse me. I deem it obvious that applications are host-my code combinations for a very specific purpose. But let me touch up my definition:
A software application consists of exactly one host assembly (EXE) and one or many custom made assemblies (DLLs) developed for a specific purpose. (Of course host as well as custom made assemblies rely on other infrastructure like operating system or .NET Framework.) The combination of my code written to solve a problem and a host containing and running the code make an application. I think, it can and should be as simple as that.
Then, if I choose to develop code to be hosted in several hosts (like a Web service running in IIS/ASP.NET on a server + a WinForms frontend running on clients + some businesslogic running in COM+ on a server and called by the Web service + some stored procedures running in SQL Server called by the COM+ components) I end up with a solution consisting of several applications (4 in this example). Why not? There is no rule saying "Thou shalt solve a customer problem with just one application." The customer doesn´t care anyway. If anything at all he will acknowledge how precisely I can speak about his solution. For the first time he will be able to understand what is meant by the omnipresent term "application"; it´s not the combination of frontend and Web service, it´s not everything together. His solution consists of several applications. And each application consist of a host and several custom made components run by the host.
I´ve given the question I posed "What is an application?" some more thought. Martin Lercher made a good point, when he wrote "deployed set of executable code, infrastructure and data such that this set is minimal" for a given purpose. And Ingo Rammer surely explains it like I would have some time ago by saying, an application is "whatever is contained in one single Visual Studio SLN file." Microsoft surely likes him for that, too :-) But still... there remains a feeling of uneasyness in me with those explanations. For one, I strongly believe, non-trivial applications (or software based solutions) should not be developed within a single VS solution. And then, Ingo says: "A certain solution - or system - however might easily consist of several applications." That means, when I set out to solve a problem and tell the customer "Hey, I´m gonna develop a nice application for you." I might be wrong? I might end up producing several applications? If that´s the case - and I believe it is - then we should define the term "application" much stricter.
I therefore propose the following:
Whatever we produce as response to a customer requesting "an application" from us is a Software Solution. It might be an Add-In for Word, or a standalone WinForms EXE, or a library to be hosted in COM+ etc.
A Software Solution is not to be confused with a VS.NET solution file.
A Software Solution possibly consists of many assemblies and additional files (e.g. database).
But most importantly, a Software Solution consists of a number of Software Applications ranging from 1 to n.
A Software Application in turn consists of at least two things: my code, i.e. 1 or several assemblies, and 1 Application Host.
The Application Host provides a runtime environment or infrastructure for my code. An Application Host always is an EXE file. And its infrastructure can be rich or simple to non-existent. The main purpose of the Application Host is loading my code and starting it. (Although the CLR is doing that, I don´t view the CLR as an Application Host. The CLR is the foundation for managed Application Hosts and my code, like the operating system is for all code running on a computer.)
There already exist quite a few Application Hosts: COM+, IIS/ASP.NET, BizTalk, IE, SQL Server 2005. To complement them for simpler Software Applications I propose we come up with a Console Application Host, a WinForms Application Host, and a NT Service Application Host. For a start, they are very simple to write, just a couple of lines of code. But their impact is considerable:
Vested with an Application Host battery ranging from Console Application Host over COM+ Application Host to BizTalk Application Host, our Software Applications can become quite simple and regular in their basic structure:
For each Sofware Application choose an appropriate Application Host - and then write all your code (your application logic) exclusively as library assemblies (DLLs).
So where does that take us? Does this definition of "application" make anything easier? I´d say so!
- We no longer need to ask ourselves, whether our solution is one or many applications. We just count the number of Application Hosts involved.
- A technology like BizTalk or SQL Server can easily be categorized: they are Application Hosts because they run our code.
- And we don´t have to ponder the question any longer what "distributed application" means. The answer is: There are no distributed applications!
There are only distributed Software Solutions. A distributed Software Solution consists of at least 2 Software Applications who communicate with one another. A simple scenario could be... a desktop app (WinForms Application Host) calling a SQL Server (Database Application Host) stored procedure. Have you ever thought of a C/S scenario as a "truw" distributed one? There is no Application Server like COM+ involved, but still... it is distributed, because there are two Application Hosts runnining our own logic. (Stored procedures of course belong to our own code.)
The longer I think about "applications" in this way, there more comfortable I feel. I can now use the term "application" very precicely, I can draw a little circle around what makes up an "application": the circle is the Application Host, what´s in the circle is my code hosted by the Application Host. And if I want to distribute my solution I just need to ask, which Application Host provides an adequate infrastructure, break my code apart, keep some in the former Application Host and put the rest into the other one. (Of course I need to observe the prerequisites and constraints of each host.)
"Application" just seems to be right as a description for whatever a host plus my code is. "Software" would be too broad a term. "Solution" would be too broad a term. "Component" would be too narrow a term.
But even though I´m quite happy with my new definition, I take suggestions for alternatives.
Maybe I´m naive or dumb, but the more I think about it, the less I know what an "application" - an application in software development - is. Can you help me? Who can give me a simple answer?
Is it a single EXE assembly? No, not necessarily.
Or is it an EXE together with all the other assemblies I write? Hm, maybe.
Is a service (as in SOA) an application?
What is a distributed application? Is it one application whose parts run on different machines? Or are these parts in themselves applications?
If I start out with a single EXE to solve my problem and later decide to split it in two: do I then have two applications? Or is it still one application which incidentally manifests itself as two EXE files?
You see, I´m somewhat confused. The more so, because when I turn to current architecture models (e.g. layered architecture, or Clemens Vaster´s onion) I don´t find an answer. Neither helps a definition like "application program".
It seems the term "application" is either overloaded with many meanings. Or it is underspecified.
But maybe someone out there can provide a (link to a ) consice definition?
In yesterdays post
I bemoaned VS.NET constraining how we develop software. Now, that I´ve thought about this a little bit more, I came to the conclusion, what I´m looking for is support for Microkernel architectures.
Microkernels (although primarily known from the OS world) are a general architecture pattern. They allow a software to be extended without recompilation/relinking.
However, the CLR primarily supports static binding with dynamic loading. Assemblies get dynamically loaded when needed, but you need to statically reference them from your project.
Of course, the CLR also allows dynamic binding by loading assemblies by hand and using Activator.CreateInstance(). But these features are not tight together into a dedicated infrastructure to set up Microkernel architectures. For example there is no concept of a "registry" for implementations of interfaces by which you could instanciate implementations indirectly thus decoupling client and service.
To reach new levels in parallel/independent development and decoupling of components, though, we must move to "Contract First" design for intra-application "boundaries". (The SOA world has recognized this already for inter-application boundaries. See Christian Weyer´s postings on his tool for Web Service Contract First programming as an example.) Currently, the services of a component are (mostly) implicitly described/determined by its implementation, the actual assembly we are referencing.
But what we need, is an independet explicit description (a formal interface definition) against which we programm. And which only at runtime is dynamically linked to an implementation.
This of course entails changes in how we test/integrate our applications. But it also allows for many improvements in the process of application development from design to maintenance.
Have you ever pondered the current practice of referencing assemblies from within a VS.NET project? I haven´t much until recently. I just took this way of linking to code for granted. It´s how we do dynamic linking today. Great!
Or isn´t it?
No, I don´t think it´s that great. I think it limits our thinking on how we develop software. It is just one way to link components together at runtime.
What´s limiting in referencing assemblies is that it binds the component under development to a certain implementation of other components. Isn´t that, what we want, you might ask? Yes, sure, that´s what we need and want for components that already exist (lets call them libraries) while we develop our own component.
When I work on my component, I need the services of libraries like the .NET Fx DLLs or the assembly of my favorite DataGrid. Those libraries exist prior to my project, their interfaces are set, their implementation is complete. So, sure, I should be able to include their services into my component by setting a reference to them, thereby importing not only their meta data, but also later on during runtim loading concrete assemblies.
But when I want to do real component based development (CBD), then I consequentially want to divide my own application up into several modules/components. These components will be developed by several programmers in parallel. This will often lead to situations where a developer working on component A needs component B - which is still under development. But this scenario is not well supported by VS.NET or the .NET Fx.
I cannot reference an assembly that does not exist yet. So what should I do in my project? There are several ways out of this dilemma. The one chosen most often is not to develop components at all. Next comes building huge solutions with many, many projects in them. Both ways sooner or later lead to tight coupling between components and thus thwart the vision of CBD.
But there is a third way: I could define interfaces for components first and put them in a separate assembly. This assembly I could readly reference in my component A project. I´d then know how to use component B thru its interface IB. Great!
Or isn´t it?
Yes, a very good idea - but no well supported by VS.NET and the .NET Fx. Because this way entails you need to discover the implementation of the interfaces you bind to during runtime. Currently there is no way to accomplish that. You can´t pass an interface type to Activator.CreateInstance() and ask it to instanciate an unknown class implementing that interface.
But that´s what´s necessary if you truely want to decouple a client component A from the implementation of some interface IB. Because during development of A you might use mock-up component BMockup which implements IB. But later on a client´s system BMockup has to be replaced by BFinal. Or maybe you want to try different implementations of IB, e.g. BStrategy1 and BStrategy2. How do you bind to those different implementations during development? Not at all, because they don´t exist.
That´s what I mean, when I state, VS.NET contrains the development process. VS.NET and the .NET Fx are targeted towards developing applications where all implementations are well known during development time. It supports well bottom-up development. But it does not support well parallel, independet development. We still need to come up with additional infrastructure to overcome these limitations. We need to build our own Contract First tools for intra application interfaces between components.
I have to admit, yesterday´s posting on Microsoft´s olfactoric tool Code Smell Cop (CSCop)
was an April Fools Day joke. But still... I´d like to see tool support for more than our eye and ear senses. What about tactile feedback while programming, e.g. depending on amount of code in a method or class or assembly?
More Posts Next page »