Sponsored Links


Resources

.NET Research Library
Get .NET related white papers, case studies and webcasts

The Intersection of Objects and ServicesThe Intersection of Objects and ServicesThe Intersection of Objects and Services Discuss DiscussDiscuss Printer friendly Printer friendlyPrinter friendly
The Intersection of Objects and Services

February 23, 2005

The intersection of object-oriented (OO) design and service-oriented (SO) design is an interesting space. SO is the younger concept, and is very much still evolving and changing day to day. Still, there are two major schools of object thinking, and correspondingly there are two emerging schools of thought in the SO space.

The question of where OO design can fit into SO designs is of interest. The mature ideas of OO have substantial value, and if we can apply some of that value to SO applications then so much the better.

Object Thinking

OO is based on object thinking. There are two primary schools of OO thought:

  • Objects are defined by behavior. This includes CRC style analysis and design, and focusing on the behavior/responsibilities of an object rather than the data/state it might contain.
  • Objects are “smart data containers”. They encapsulate both state and the logic required to manage or interact with that state. Analysis and design is typically done using UML and is often relatively data focused.

In both cases, it is widely accepted that OO technologies are defined by encapsulation, abstraction, polymorphism and inheritance.

Components

When talking about objects, we must also talk about components. Component-based or component-oriented (CO) concepts started to come into vogue in the mid to late 90’s. The movement got sidelined by the dot-com bubble and the industry’s shift away from formalism toward creating throw-away software. By the time we woke up and realized that was a dead-end, the opportunity for CO was past and we were moving steadily toward SO.

But to understand SO we need to at least recognize that there are a couple definitions of component:

  • Components are super-objects. They are objects (in the OO sense) that collaborate or encapsulate numerous other objects and provide a higher-level interface to the underlying complex interactions.
  • Components are binary reusable entities that are a unit of deployment. They expose a formal, contractual interface and can be invoked by other compiled code locally or across the network via specialized protocols.

Of these two definitions, number 2 is the one that is typically first in people’s minds. This is the model popularized by COM and CORBA, then later by J2EE. While some object purists cling to definition 1, the reality is that “components” are defined by most people as binary reusable entities.

Service Thinking

SO is young and evolving. I am convinced that it will be based on service thinking once there is such an idea. There are two primary schools of thought in the SO space as well:

  • Services are components (like COM) on the web
  • Services are messaging endpoints

People have characterized services as being “objects on the web” or just an “API on the web”, but these two approaches have gained little traction.

Virtually all OO people consider polymorphism and inheritance to be OO requirements. SO doesn’t have those concepts (though you can argue that it has a limited variation on polymorphism). Thus SO can’t really be “objects on the web”.

The idea of services being an “API on the web” is sound and makes sense. This train of thought says that a service is nothing more than a collection of atomic procedures or methods. Because each procedure is independent from any other, what we really have is just an API – a set of procedures that do work, each of which can be invoked by a caller.

But this idea is really just a subset of the more popular “components on the web” idea. Many people take the idea of services as being “components on the web” seriously. Given our collective experience with DCOM, MTS/COM+ and CORBA, it is very easy to understand how to design systems based on components that can be called across the network.

We’ve become pretty good at building components, and web services technology offers a new protocol through which to interact with such components. While SO and web services are not the same thing, they are the same thing in most people’s minds. Unfortunately perception is reality, so in the end SO and web services are the same thing. Thus, in most people’s view it is fact that SO is just another way to do component-oriented design and development. A better way, since it is an Internet and firewall friendly approach (as opposed to DCOM and other previous protocols).

Personally I fear that the battle is lost. Too many people think SO equals web services, and thus SO is just a rebirth of component-oriented design and programming using HTTP/XML protocols instead of DCOM, RMI or IIOP.

However, I’m not ready to give up hope for what I believe is the better definition. This is the idea that services are messaging endpoints. This is a view championed by people like Microsoft’s Pat Helland. In this view services are not components. They do not accept parameters and do not expose an API as such.

Rather, a service accepts a message and acts on that message as it sees fit. If it returns any results, those results are also a message, which is sent back to the original caller. These messages are defined by a schema. In an ideal world, all this message passing is viewed as being asynchronous, meaning that the process becomes independent from web services and can work equally well through queuing technologies, email messages, IP sockets or anything else that can move data.

This definition is exciting because it is somewhat new and certainly is very different from the component-oriented definition of services. What we’re really talking about here is the creation of distributed parallel systems that interact with each other via well-defined messages.

As cool as this might be, I’m becoming convinced that precious few people will ever go down this road. It is too big a shift, especially when SO and web services have already been largely co-opted by the component-oriented design world.

Still, let’s discuss the intersection of OO and SO in the context of both component-SO and message-SO.

Intersection of OO and Component-SO

If we settle on component-SO where services are very comparable to COM or CORBA objects, but are accessible via HTTP/XML, where do OO concepts fit into the picture?

There are several areas to consider. The following table summarizes the areas and whether OO plays a role:

The client implementation

Client can be purely OO

The client-side proxy for the service

Proxy can be OO, and expose OO interface to the client

The parameters/data sent to/from the service

For interop data must be open and generic; for n-tier data can be complex objects

The design of the service interface

Service interface is not OO

The service implementation

Implementation can be purely OO


Client Implementation

If a service is a component, then there is a client that is interacting with that service/component. The client might be another service/component, but more likely it is an actual client like web or Windows UI code. Either way, the client code may be designed in various ways, including OO.

It is totally realistic to expect that a client will be constructed following OO design, with the UI interacting with a set of business objects. Those business objects will “persist” themselves via the service/component rather than directly to any database. The end result is that the client code would be essentially normal code designed with OO. Instead of ADO.NET persistence code, it would have web service code.

Client-side Proxy

Which leads us to a discussion of the actual communication with the service/component. This is typically handled by a client-side proxy for the service. This proxy may be a simple type wrapper like those generated by VS.NET, or it could be more sophisticated like the DataPortal in my CSLA .NET framework. Or it could be a combination of both.

The proxy itself can be designed following OO principles. But more importantly, it can provide access to the service/component in an OO way. This means that the client code would not have to realize it was using web services, WSE or Indigo, but rather would just interact with the abstract, OO proxy for the service/component.

This can be achieved by combining the concepts of Fowler’s Gateway pattern or my DataPortal along with generated type proxies for the data types transferred between client and server (like those generated today by VS.NET). This way, even non-OO client code has a pure OO service/component interface.

Parameters on the Wire

Of course the parameters/results passed on the wire between client and service are just bytes. The client-side proxy may provide an OO façade, but ultimately the data is just bytes on the wire.

That level of detail isn’t instructive however. So let’s step up a level and consider what data might be passed on the wire:

  • Simple types like Integer or String in XML form
  • “Documents” like a DataSet or data transfer object in XML form
  • State of a serialized business object as a byte array

The first two options are passing the data in an “open” format which is conducive to interoperability. If our intent in using component-SO is for interoperability then we must restrict ourselves to those options.

In an interop scenario the client and server/component are logically two separate applications. These two applications are using SO technology to communicate between each other in a relatively tightly coupled manner, but still they can’t be so tightly coupled as to share low-level object types as implied in the third option. They must stick with the more open data that can be represented in XML form.

However, many people will be using component-SO for n-tier development in the same way we used DCOM, RMI or remoting in the past. In this case the third option is entirely practical. In an n-tier model, the client and service/component are logically part of the same application. Only the client will interact with the service/component, so interop and reuse are not key factors here. Instead, functionality and performance are key factors. Being able to pass complex object graphs, including semantic meaning, between tiers is powerful and is enabled by the third option.

Service Interface

A service/component is merely a group of procedures or methods. For good design, these procedures would have some cohesion, but technically that is not required. To achieve scalability, reliability and maintainability, these procedures will be atomic and stateless.

Atomic means that each procedure stands alone. It doesn’t rely on previous or subsequent procedures being called.

Stateless means that the procedure doesn’t rely on previous state to exist, nor does it leave state behind for subsequent procedure calls. This isn’t to say that state won’t exist in a database or some other location, but it doesn’t exist within the context of the procedure itself.

We’re also talking about building service/component entities using technologies such as web services, WSE or Indigo. And perhaps with queuing technologies. None of these technologies are object-oriented, since they don’t support inheritance, nor do they really support polymorphism.

Due to the atomic and stateless nature of the procedures, any encapsulation provided by a service/component is also somewhat limited – at least when compared to what is possible in an actual OO environment.

The end result is that service/component interfaces lack 3 of the 4 criteria required for OO design. This means that the interfaces cannot be thought of in OO terms. Rather they are best thought of in procedural terms. Literally they should be thought of as a set of (hopefully related) procedures, much like a FORTRAN function library.

As we discussed earlier, this doesn’t preclude the creation of an OO façade in the client-side proxy. But it is important to recognize that the OO nature of the client-side proxy doesn’t imply that the service interface itself is OO.

Service Implementation

Finally there’s the implementation of the service/component itself. Like the client implementation, the service can be implemented in many ways, including following OO design and programming.

Ultimately the data flowing into and out of the service will be through its non-OO interface, but that doesn’t prevent the mapping of that data into an OO form for use inside the service. This is very comparable to the impedance mismatch issue faced between relational data and OO implementations, in that the data outside the bounds of our code is not in any OO form, and we must translate into and out of an OO form as the data flows into and out of our service.

The bigger question is whether it is cost-effective to do this translation from the non-OO world to the OO world. Is there enough benefit to having an OO design inside the service to justify the code required to do the translation of the data?

The answer is different for different services. Many services merely act as gateways to a database or other data store. They do little actual processing or work on the data. In such cases it is hard to imagine justifying translation of the data into objects, when those objects do little to no actual work.

Some services do some work on the data, and others are very sophisticated and implement complex logic and behavior. The more complex the logic, the more sophisticated the behavior, the easier it is to justify translating the data into objects before triggering the actual business processing.

So in the end it is a scale, on one end it doesn’t make sense to be OO and on the other end it makes a great deal of sense. Unfortunately most services will fall into the gray area in between and whether to be OO or not is a case-by-case decision.

Intersection of OO and Message-SO

Finally, let’s look at message-SO where services are messaging endpoints, and all communication is via idempotent messages. In this case, where do OO concepts fit into the picture?

There are several areas to consider. The following table summarizes the areas and whether OO plays a role:

The calling service

Calling service can be purely OO

The proxy for the provider service

Proxy can be OO, and expose OO interface to the calling service

The messages passed between the services

Messages are defined by data-focused schema and are not OO

The design of the provider service interface

Service interface is not OO

The provider service

Implementation can be purely OO


If you look at these areas, you’ll note that they are very similar to the areas we discussed with component-SO. However, there are differences. I’ll focus only on the differences in this section.

Note that in this new context there are no “clients” as such. In this model everything is a service, and services can interact with each other as needed. Anything we would consider a “client” in an n-tier model is merely another service that interacts with a user.

Also keep in mind that each service is autonomous and that there is no trust between different services. Each service is an independent application that may be used by any other independent application (service). Not only do services not trust each other from a security perspective, but they don’t trust each other’s logic or behavior.

Finally, services communicate by passing messages. Essentially there is only one method signature for all service procedures:

resultMessage = f(requestMessage)

Where resultMessage and requestMessage are messages conforming to a schema defined by the Provider Service.

Calling and Provider Service Implementation

As with a service/component, both of the message-endpoint services can be implemented in many ways. One option is to use an OO design inside the service.

The same issues apply, in that the messages are not objects. They are non-OO data, and so there is an impedance mismatch between the message data and any OO design that might be used inside either the calling or providing service. It is important to weigh the cost of the code to translate between messages and objects on a per-service basis to determine whether the value is there to justify the cost.

Proxy for the Provider Service

As noted, the Calling Service might or might not be implemented with OO design. Either way, it will need some mechanism by which it can interact with the Provider Service. Typically this is done through a proxy.

The proxy itself can be created following OO design. There are two parts to this. One is the representation of the remote service itself, the other is the representation of the resultMessage and requestMessage schemas.

Of the two, the schema representations are probably the most important. They are often generated by tools such as VS.NET, and thus are expressed in the proxy as classes. However, they are not typically OO in terms of OO design, but rather are merely vessels that reflect the format of the data required by the message schema. They are, at best, data transfer objects.

Messages on the Wire

The messages themselves are, like any other data, just bytes on the wire. Nothing more, nothing less.

The messages themselves can be viewed as objects – but only in a limited sense. They do not encapsulate any behavior or semantic meaning. They merely provide data, at most with some basic syntactic validation. From any level of OO purity, the messages are not object-oriented.

It is better to view them as pure data. This is especially true when you consider that messages can go through intermediate processing steps as they travel between the Calling Service and the Provider Service. These intermediate processing steps might transform or alter the message in various ways. These are things that are done to data, and fly directly in the face of good OO practice. Thus it is best to just avoid OO metaphors and realize that messages are simply data.

Provider Service Interface

The elements to consider here are the same as with a service/component. The only real difference is that in a message-based service world all services have the same method signature as discussed earlier. The real interface is the schema of the requestMessage and responseMessage.

Summary

Object-oriented design flows from either of two primary schools of object thinking (objects as behavior, or objects as smart data containers). Service-oriented design flows from either of two primary schools of service thinking (services as components, or services as message endpoints).

In each case, client and service implementations can follow good OO design if desired. In any case, the client or calling service will use a proxy to interact with the provider service, and there is value in using OO programming and possible design in the creation of the proxy.

The data on the wire is never OO, it is just data. This means there’s an impedance mismatch as the data flows into and out of a service implemented with OO design. Overcoming this mismatch has a cost. The more complex the behavior/logic of the service, the more worthwhile it is to implement the service using objects.

While SO design is fundamentally different from OO design, there are areas of intersection, where the use of OO design has substantial value to the overall system architecture.

Authors

Rockford Lhotka is the Principal Technology Evangelist for Magenic Technologies, a company focused on delivering business value through applied technology and one of the nation's premiere Microsoft Gold Certified Partners. Rockford is the author of several books, including 'Expert One-on-One Visual Basic .NET Business Objects' and 'Expert C# Business Objects'. He is a Microsoft Software Legend, Regional Director, MVP and INETA speaker. He is a columnist for MSDN Online and contributing author for Visual Studio Magazine, and he regularly presents at major conferences around the world - including Microsoft PDC, Tech Ed, VS Live! and VS Connections. Rockford has has worked on many projects in various roles, including software architecture, design and development, network administration and project management. Over his career he has designed and helped to create systems for bio-medical manufacturing, agriculture, point of sale, credit card fraud tracking, general retail, construction and healthcare.

News | Blogs | Discussions | Tech talks | White Papers | Downloads | Articles | Media kit | About
All Content Copyright ©2007 TheServerSide Privacy Policy
Site Map