Software Cells #4: Contracts everywhere

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 ;-)

4 Comments

  • Another fine entry in your series!



    You lost me at a few points; and it’s probably just my own ignorance. But, by CTS as in “Contracts are defined using the CTS”, I believe you are using an acronym to stand for the “component type system”, but I’m not sure?



    Secondly, towards the end of the blog you state “To use the services of another Component code only binds to the Component’s contract (interface), but never to its implementation (a concrete assembly).” Should this really say “To use the services of another Component code only binds to the Component’s contract (interface), but never to its implementation (a concrete type).”? I would think the granularity involved with describing interface definition, class/type definition, and their construction into assembly definitions would be left up to the practices and development environment involved with a particular application (Software Cell) build process. Unless of course your Software Cell biology ;-) does demand that each component be an explicit assembly, and that might be the case.

  • @Scott: By "CTS" I mean the .NET Common Type System, i.e. the "usual" interface types you can define using C# oder VB.



    "Binding to an interface instead of an implementation" means to reference only assemblies containing interface definitions instead of interface implementations. Component A which wants to use a service defined by interface J should not know or depend on which component, i.e. assembly, actually implements interface J. This is only resolved at runtime.



    VS on the other hand forces you to reference an implementing assembly at designtime. That´s static binding. It makes instanciating classes easy, but it couples the caller closely to an implementation which is bad for parallel development and decoupling.



    I´ll talk about this kind of dynamic binding in a future posting to clarify what I mean.

  • "Inter-Solutoin Contracts should without exception be defined using WSDL and XML Schema" - this isn't backed up in your article; even though I agree with it :)



    It's all about versioning.



    There's one thing missing from your discussion, though. You give a thorough treatment to what I call "syntactic interfaces" or contracts, but don't go into "semantic interfaces".



    It's always the semantics that complicates things, probably because we don't have a compiler to check it.

  • @Udi: The series (so far) is not much concerned with specific technologies. What I wanted to point out when saying, one should use WSDL at inter-solution boundaries was, crossing a platboundary needs special consideration.



    Semantic versioning of course is an unsolved problem. It´s too large for me ;-) so I stick with proven concepts like "syntactic interfaces" (regardless of technology: CTS, WSDL).

Comments have been disabled for this content.