The Network is the Container

Friday, August 28, 2009

One of the standout features of Spring, with its declarative approach to so-called "cross-cutting concerns", has been to help separate infrastructure minutiae from day-to-day programming and allow a cleaner focus on business logic. However, that only lasts up until the time the application has to be deployed.

With the acquisition of SpringSource by VMWare, the Spring team has set a new goal to abstract infrastructure details away from day-to-day operations.

"VMware and SpringSource plan to further innovate and develop integrated Platform as a Service (PaaS) solutions that can be hosted at customer datacenters or at cloud service providers."
Deploying and managing enterprise applications is hard, and what makes "enterprise" applications "enterprise-y" is not just about how much they integrate or how critical they are to how many lines of business. "Enterprise" applications operate in an enterprise context, that is, they conform to consistent, independent infrastructure capabilities that serve many applications: authentication and single sign-on, authorization, transaction management, fault and performance monitoring, data security, audit compliance, routing, caching and more.

These common capabilities are built to economies of scale such that the net investment required to make them common is a good deal less than the cost for each application to provide them on its own. The downside is they are highly tailored for the local environment, difficult to port into and out of, and create significant overhead for testing and deployment.

The traditional application server is little more than a bridge into this environment; the real "container" for enterprise applications is the network on which they operate, and the promise of commoditized platform-as-a-service will not be realized until more of these common capabilities and their configuration can be virtualized and automated to the same degree as hypervisors have for the O/S.

In his frequently quoted blog entry on the acquisition, Ovum analyst Tony Baer writes:
"The fact is that providing a virtualization engine, even if you pad it with management utilities that act like an operating system, is still a raw cloud with little pull unless you go higher up in the stack. Raw clouds have their appeal only to vendors that resell capacity or enterprise large firms with the deep benches of infrastructure expertise to run their own virtual environments."
And later:
"VMware isn’t finished however. The most glaring omission is need for Java object distributed caching to provide yet another alternative to scalability. If you only rely on spinning out more VMs, you get a highly rigid one-dimensional cloud that will not provide the economies of scale and flexibility that clouds are supposed to provide. So we wouldn’t be surprised if GigaSpaces or Terracotta might be next in VMware’s acquisition plans."

They certainly have already have the strategic relationship with Terracotta. That covers caching, and the earlier acquisition of Hyperic by SpringSource covers operations management to some degree.

It's not clear to what extent outright acquisitions are needed to build out this distributed "container". For example, the Cisco Nexus 1000v is an independent software switch product, and there is even an open source competitor to same (not for for the faint of heart, presumably.)

Another interesting and underrated problem area is data service security. Certificates expire, passwords change frequently, and both tend to be managed through manual processes. That's a serious obstacle to on-premises dynamic provisioning, much less when operating in external clouds. Something like Digital Vault technology from CyberArk might fit the need.

Comments welcome. What else is needed to make PaaS into a product, or suite of products, that can be "installed" on-premises? Can you achieve dynamic database capacity without affecting existing DB-backed applications? Where does identity management fit in? What technologies would have to be acquired, and where will partnerships suffice?

(Disclaimer: The above opinions are mine alone and do not necessarily represent the views of current or former employers.)

Falling Up the Stairs, Part 1: A Line-by-Line Conversion

Monday, July 13, 2009

As I noted in the first of these articles, I plan to dive right in rather than teach Scala from scratch as if to new programmers. So I'll begin with a translation of a simple, real-world development problem from Java to Scala, just to give the flavor of the language and highlight a few key capabilities & differences from Java.

The problem, taken from an old unit test suite, is to generate a web application directory on the fly for use by an embedded servlet container. We'll focus on one aspect, the creation of web.xml. Our code will allow a test suite to specify servlet context parameters, servlet classes and URL bindings, and return the appropriate web.xml file as a string. Here's how it's used:


WebXmlGen gen = new WebXmlGen();

gen.addParam("initConfig", "WEB-INF/myconfig.xml");

gen.addServlet("main", "myapp.tests.Mainervlet").bind("/");
gen.addServlet("test", "myapp.tests.TestServlet").bind("/test");

new FileWriter("WEB-INF/web.xml").write(gen.webXml());

For the Java code, we'll need a list to hold the servlet configurations, another list for the context parameters, and helper classes for each we'll call ParamInfo and ServletInfo.


import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import org.jdom.DocType;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Text;
import org.jdom.output.XMLOutputter;

public class WebXmlGen1
{
private List<ServletInfo> servlets = new ArrayList<ServletInfo>();
private List<ParamInfo> params = new ArrayList<ParamInfo>();

The webXml method will use JDOM for generating the XML, and will delegate to XML-generating methods in ParamInfo and ServletInfo:


public String webXml() throws IOException
{
Element root = new Element("web-app");
Document doc = new Document(root);
doc.setDocType(new DocType("web-app",
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",
"http://java.sun.com/j2ee/dtds/web-app_2_3.dtd"));

for (ParamInfo ps : params)
ps.addXml(root);
for (ServletInfo ss : servlets)
ss.addServletXml(root);
for (ServletInfo ss : servlets)
ss.addMappingXml(root);

XMLOutputter xo = new XMLOutputter();
StringWriter output = new StringWriter();
xo.output(doc, output);
return output.toString();
}

The helper class for holding parameter information is straightforward, just a place to stash the parameter name & value. Its addXml() method adds the <context-param> element to the JDOM Document.


private class ParamInfo
{
String name;
String value;

ParamInfo(String name, String value) {
this.name = name;
this.value = value;
}

void addXml(Element root) {
Element paramName = textElement("param-name", name);
Element paramValue = textElement("param-value", value);
Element param = new Element("context-param")
.addContent(paramName).addContent(paramValue);
root.addContent(param);
}
}

Given this definition, here is the addParam method:


public void addParam(String name, String value) {
params.add(new ParamInfo(name, value));
}

Next, there is the ServletInfo class; it holds the name and class of the servlet, a list of URL patterns to map to the servlet:


private class ServletInfo
{
String name;
String klass;
List<String> patterns = new ArrayList<String>();

ServletInfo(String name, String klass) {
this.name = name;
this.klass = klass;
}

void addServletXml(Element root) {
Element servletName = textElement("servlet-name", name);
Element servletClass = textElement("servlet-class", klass);
Element servlet = new Element("servlet").addContent(servletName)
.addContent(servletClass);
root.addContent(servlet);
}

void addMappingXml(Element root) {
for (String pattern : patterns) {
Element servletName = textElement("servlet-name", name);
Element urlPattern = textElement("url-pattern", pattern);
Element mapping = new Element("servlet-mapping").addContent(
servletName).addContent(urlPattern);
root.addContent(mapping);
}
}
}

Here is the addServlet method. To avoid exposing the ServletInfo class to callers, we define an interface that supports the bind() method shown earlier, and return an anonymous class instance that implements the interface.


public interface UrlBinder {
UrlBinder bind(String pattern);
}

public UrlBinder addServlet(String name, String klass) {
final ServletInfo info = new ServletInfo(name, klass);
servlets.add(info);
return new UrlBinder() {
public UrlBinder bind(String pattern) {
info.patterns.add(pattern);
return this;
}
};
}

Finally, there is a convenience method for building elements containing a single text node.


private Element textElement(String name, String text) {
return new Element(name).addContent(new Text(text));
}

Easy enough. Let's begin the translation and introduce some of Scala's improvements. Here are the first few lines of the class as expressed in Scala:


import java.io.StringWriter

import scala.collection.mutable.ListBuffer
import scala.xml.XML
import scala.xml.dtd.{DocType, PublicID}

class WebXmlGen2
{
private var servlets = new ListBuffer[ServletInfo]()
private var params = new ListBuffer[ParamInfo]()

The class definition is familiar enough; it works the same way as in Java, however the default modifier is public. As you also may have guessed, type parameterization uses square brackets, not angle brackets, so you write ListBuffer[ParamInfo] rather than ListBuffer<ParamInfo>.(ListBuffer is one of Scala's collection classes; you can also use java.util collections.)

What's clearly missing here is the "double declaration" boilerplate found in Java. Because of Scala's type inferencing, you needn't declare the type of a field or method if Scala can intuit it from an initializer or a return value; just use "var" or "val" to indicate whether the field is mutable or not (can change after assignment.)

Also missing are explicit line terminators; it's hardly ever necessary to put a semicolon in Scala code.

Next we'll translate the addParam and addServlet methods. These also are straightforward:


def addParam(name: String, value: String) =
params += new ParamInfo(name, value)

trait UrlBinder {
def bind(pattern: String): UrlBinder
}

def addServlet(name: String, klass: String) = {
val info = new ServletInfo(name, klass)
servlets += info
new UrlBinder {
def bind(pattern: String) = {
info.patterns += pattern
this
}
}
}

New concepts:

  • Names and types in declarations are reversed, a la "name: type" rather than "type name".
  • Instead of interfaces, Scala uses traits, which can express both function contracts and behavior. More on this in another post; in this case, our use of a trait is the same as the use of an interface in Java.
  • Functions are introduced using the def keyword. Braces are optional around functions because the body of a function is simply an expression, and in Scala a block of statements is also an expression. It can be used anywhere, not just for lexical structuring purposes as in Java. The value of a block expression is the value of the last contained expression, so a return statement is optional in this case.

Note again that we haven't declared the return type of these functions: Scala has inferred them from the return values. OK, nothing too revolutionary so far; next we redo the webXml() method:


def webXml = {
val nodes =
<web-app>
{params.map(p => p.toXml)}
{servlets.map(s => s.servletXml)}
{servlets.map(s => s.mappingXml)}
</web-app>
val out = new StringWriter()
XML.write(out, nodes, "utf-8", true,
DocType("web-app", PublicID(
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",
"http://java.sun.com/j2ee/dtds/web-app_2_3.dtd"), Seq()))
out.toString()
}

Whoa... this is different. Lines 38-41 are just serialization code from Scala's standard XML library, but what about lines 32-36?

This is Scala's support for XML literals at the language level. Writing XML from Scala means... just writing XML. The compiler checks the XML for well-formedness and converts it to an internal runtime representation. You can interpolate application data in elements or attributes using curly braces, as shown here.

Inside the braces, we see the use of function literals, a great source of flexibility that was regrettably, along with closures, dropped from Java 7. Function literals allow function definitions to be used as values and passed around just like instances of built-in and user-defined types. The syntax of function literals is

(arg1: type, ..., argN: type) => expression

Parentheses may be left off the arg list if there is only one argument whose type can be inferred. So the expression

params.map(p => p.toXml)

is the same as

params.map((p: ParamInfo) => p.toXml)

because Scala knows the argument list of a function passed to ListBuffer[T].map is of type (T). What this says, then, is "Take each element of params, apply the toXml method, and return a sequence of the results." Since the type of each sequence member is in turn inferred to be an XML node (because ParamInfo.toXml returns XML) Scala will add those elements as children of the <web-app> element; likewise with the XML for the servlet definitions.

Continuing on, you will now probably not be surprised by the definition of the ParamInfo class:


private class ParamInfo(name: String, value: String)
{
def toXml =
<context-param>
<param-name>{name}</param-name>
<param-value>{value}</param-value>
</context-param>
}

Or maybe you will be... where's the constructor? It's created automatically by appending an argument list to the class name as shown. More boilerplate gone; no need to populate member fields by hand.

Finally, there's the updated ServletInfo, and no new surprises this time:


private class ServletInfo(name: String, klass: String)
{
val patterns = new ListBuffer[String]()

def servletXml =
<servlet>
<servlet-name>{name}</servlet-name>
<servlet-class>{klass}</servlet-class>
</servlet>

def mappingXml =
patterns.map(pattern =>
<servlet-mapping>
<servlet-name>{name}</servlet-name>
<url-pattern>{pattern}</url-pattern>
</servlet-mapping>)
}

What have we accomplished so far with Scala? We've eliminated useless boilerplate at several points, because the Scala compiler will intuit information that the Java compiler forces the programmer to specify. We've used expression-oriented syntax to describe operations on collections more concisely than in Java. We've generated XML in the most natural way possible: using XML syntax, instead of through an API. We've reduced the code size by about a third.

Best of all, the result of compiling the Scala version is plain old Java bytecode. The Scala version of WebXmlGen can be instantiated from Java, deployed in a JAR, debugged in Eclipse, or profiled for performance tuning.

SOA's Funny Hat

Sunday, January 11, 2009

One of our frequent failings in IT is the inability to recognize when what looks like a shiny, new, exciting and difficult problem requiring great innovation and finesse is really a stodgy, old, well-understood problem wearing a funny hat.

Service-oriented architecture is this in spades. SOA isn't the real problem; it's the funny hat. The real problem is software reuse.

At one time, ten years ago and more, we dreamed of composing applications from libraries of modular business components, built by domain experts, offering that magical combination of being just specific enough for our needs, and just general enough for everyone else's.

It didn't happen. Bedeviled by the intricacies of requirements variance, platform incompatibility, code dependencies, and a host of management headaches, we moved on. Instead, we now dream of composing applications from modular business services.

Technically, the idea isn't as far-fetched as it once was, as SOA offers two critical advantages over direct code reuse: platform independence and location independence.

If I want to reuse code as a component, I am obliged to use the hosting platform and framework / container, else it won't give me the time of day (even if it's a time-of-day component.) Otherwise, I have to shoehorn the framework into my established, pristine application architecture, or jettison mine and rebuild.

If I want to reuse code as a service, it's different. With web services, for instance, I send an XML message over HTTP.

And I'm done.

The impact on my application is minimal. I can use only what I need and ignore the rest. The code can be hosted anywhere and I can call it from anywhere else. You can upgrade the code a hundred times a year, change development platforms, push it out into the cloud or drag it back in-house; if the interface contract is honored, my client won't care. (Well, it won't care, modulo the odd glitches from half-wit SOAP stacks.)

Small wonder people remain excited about SOA, that even after ten years of hype and high-profile failures, we are still willing to beat our heads against this wall. It's worth the effort. When you get it right, the cost to reuse is nearly zero.

Technically, that is. SOA may have taken most of the platform issues out of software reuse, but it has done nothing to solve the far more challenging issues in managing reuse. These are well understood, but they still give reuse all the approachability of a feral pig. SOA is a beast for much the same reasons.

  • Reuse isn't just a different style of programming. It takes a highly disciplined approach, like feature-oriented domain analysis, to partition application functionality and identify critical reusable parts, and then focus investment on those parts. In SOA, it's about partitioning business functions and business processes, potentially re-engineering what's broken, and investing in those with the greatest potential.
  • Reuse brings disruptive change to the development organization. Talent is split between component builders and application builders, creating competition for who builds what. Same with SOA: you have service providers and service consumers.
  • Vendors are eager to portray technology as the solution. Reuse is achievable if only you will use our repository product, our base framework, our architecture planning tools, our software assessment suite. Likewise SOA: you can have it out of the box if only you purchase our ESB, our service registry, our governance solution, our data integration engine. Always eager for silver bullet solutions, IT managers get suckered time and again.
  • Reuse demands a different funding model. Component consumers are developers, not business users, and business sponsors are loath to pay for development of software that customers can't see and touch, or that isn't tied to specific projects. Developing an effective ROI model requires a high level of maturity in project management and accounting. The same goes for services.
  • Reuse also demands changes in business product planning. IT can't just be an order taker for the business, building applications in silos. Long-term ROI demands the reusable component base be a foundation for future products, and product planning must run in parallel with a roadmap for the components. Same with services.
Common pitfalls abound: trying to run the reuse teams like any other project , instead of like an internal product organization; use of shady ROI metrics like # of lines of code reused; failure to train developers and architects in new skills; ambitious executives over-selling pet platforms and methodologies as the key to success.

It's all too familiar. Sadly, SOA is just different enough from component reuse that we see it as a unique problem, and costly lessons from the halcyon days of software reuse go unheeded.

We ought to take another look at SOA and say, "Wait a minute… I recognize that guy."

The Last Priesthood

Tuesday, December 16, 2008

The early days of computing were not a good time for lean processes to thrive. Cycle time was atrocious. It often wasn't possible to even run a program without manual intervention; you brought a stack of cards to the priests of the temple, who interceded with the computer god on your behalf and returned the answer.

Over time, as advances in computing brought steadily more power to developers and end users, such intercessionary roles in computing dwindled. Today, they are largely limited to the far end of the development cycle, where applications move out of dev / QA and into the data center. Hands-on installation and configuration are commonplace in bringing apps to production.

The advent of cloud computing will bring more than change; it is bringing disintermediation. In short order, the cloud model (whether outsourced or in-house) will eliminate a wide range of operations tasks, bringing an end to the last priesthood of software development. Automation will become pervasive in every area of the data center, and the power of the temple will be broken.

The Internet era is full of such examples of disintermediation -- Dell computer with direct-mail customized PCs, Orbitz and Travelocity with agentless travel booking -- but my favorite analogy for the effects of the cloud is from a still earlier time, when a different sort of priesthood fell before an onslaught of infidel machinery.

I was at university in the early 1980s, and had a part-time job in one of the computer centers. Every two weeks I collected my paycheck, made the half-mile pilgrimage to the bank, and waited with dozens of other supplicants for the temple keepers to summon us, at the tolling of a bell and the gleam of a holy light above the teller window, to receive our cash.

Then a curious thing called an "automatic teller machine" opened not far from my dorm, and the "bank" was now just three blocks away. Then another opened indoors, right across the hall from the pay office. Suddenly, I didn’t have to arrange deposits and withdrawals around class schedules anymore. I was no longer acting at someone else's convenience. They were now acting for mine. I abandoned the faith without a shred of remorse, never to visit the Keepers of Deposit and Withdrawal again.

Tom Peters described this disintermediation in consumer banking nicely in his Innovation Revolution seminar. (This was around the time he was starting to go off the deep end with self-branding, and much of the material is dated now, but this one quote has stayed with me for years)

"There could be nothing more humble than the two-foot-by-two-and-a-half-foot metal jaw of the ATM on the side of the bank or the grocery store. But assuming that ATM is powered by a state-of-the-art information system… it is a simple fact, ask your banker friends, that the ATM system of 1997 relative to the bank of 1970 is literally taking the place of three or four or five or six layers of management! What was a bank in 1970? It was exactly what you wanted it to be: a police station for your cash. Layer after layer of checkers stacked on top of checkers, keeping track of your bucks. And now they're gone. And now they're gone."
This is cloud computing in a nutshell. In the old world, project teams wait in the queue, applications in hand, for a limited staff to manually install and configure the machines (which may also be allocated to specific projects), manually install the apps, manually create all the rules needed for monitoring and routing.

In the new, capacity (cash) is delivered in bulk to the data center, and product teams lease it at their convenience. Application package metadata describes the needs for capacity, monitoring, routing, bandwidth and various quality-of-service details, and the cloud management software arranges it largely without intervention.

Now, the role of operations staff is clearly more advanced than that of bank tellers, and although the priesthood is clearly doomed, the personnel are not. Capacity and network planning are still in the picture, but the main focus will be on automation, and the marching orders were issued by Microsoft Chief Architect Ray Ozzie, in the 2008 PDC keynote that introduced Windows Azure: "The previously separate roles of software development and operations have become incredibly enmeshed and intertwined."

Operations must become more than a service bureau. It must be a deep and ongoing joint venture with development teams to create competitive automation that can bring applications to market as fast as possible, manage and scale them with infinite flexibility, monitor and analyze their behavior at a level of detail that turns production statistics into business intelligence.

Ops teams will also begin to draw on the highest level of development and architecture talent available in an organization, just as they do at leaders like Amazon and Google (and now, Microsoft.) Application teams will begin to see healthy competition for star programmers, who understand automation better than anyone. Management needs to present operations jobs as opportunities for innovation and career enhancement.

These changes in organization, staffing and process are imperative. If you can't accomplish them, you can be certain your competitors will. Or like as not, they will just buy salvation in a neat package like Azure or EC2.

(Disclaimer: The above opinions are mine alone and do not necessarily represent the views of current or former employers.)

Falling Up the Stairs: An Occasional Trip with Scala

Wednesday, November 19, 2008

Lately, I've spent some after-hours time exploring Scala, a candidate "next-generation Java" that combines functional and object-oriented features.

It's intriguing. I have that slowly growing sense of excitement I've felt when discovering some of the other standout tools in my repertoire: Eclipse, Emacs, Ruby, Spring, and Hibernate, for instance. It has an elegant combination of features that relieves a wide range of programming annoyances.

Scala offers direct-to-bytecode compilation and seamless two-way interop with Java without the performance issues introduced by Groovy metaclasses. It can achieve the reduction in boilerplate code I've seen with Ruby syntax and mixins and type extensions, without sacrificing the static typing that eases maintenance and integration in large systems. And it offers functional behaviors without diverging from a reasonably Java-ish look and feel, which makes it an easier pitch to organizations using Java.

So in the name of lending another voice to the cause, I will offer an occasional article on my experiences with the language. Rather than spend time attempting to teach it from scratch, I'll simply assume high fluency with Java and relate Scala to Java as best I can. (I am sure my efforts will prove amusing to Scala gurus, hence the theme "Falling Up the Stairs." :-)

I will also aim for examples that resonate with most Java application developers, because frankly, Scala can be daunting. Some of the material offered by the admittedly excellent Programming in Scala and by online tutorials is more familiar to computer language experts; I've talked to a few workaday programmers who felt put off by this and as a result questioned the relevance to "real-world problems."

Finally, I hope to help dispel the myth that adding languages to an environment always adds complexity. This view is generally held by management, which for the most part still equates languages with platforms. In that mindset, a new language is supposed to mean costly tools and training, long ramp-up times, sparse and poorly documented libaries, no leverage of established applications, and new development silos out of which teams can no longer share code or skills.

Thanks largely to wide use of virtual machines, this is no longer true. Rather than build from scratch, more language designers are now choosing to build on the Java and .NET platforms, whose SDKs also offer a vast established feature set and allow new code to coexist with more traditional languages like Java and C#.

In the VM world, learning a new language is not much different from learning, say, Spring or Hibernate. You inhale a six-hundred-page manual, get comfortable with some new concepts and syntax and libraries, and then set about improving maintainability and time to market, with the rest of your work environment intact. Idiomatic fluency of course takes time, but that's true of any technology with a rich feature set.

The point is that the language is just a tool; it's not a different world where everything is foreign and strange. You can pick and choose the parts of an application that can most benefit from the alternate language, and apply it to only those.

Ultimately this will lead to a style of programming where it will be as natural to pick the right language for a task as to pick the right libraries. And as several well-regarded programmers have already commented on this topic, I won't sermonize further.

On to Scala.

(Disclaimer: The above opinions are mine alone and do not necessarily represent the views of current or former employers.)

SOA: What's It For?

Monday, September 29, 2008

The Gartner "hype cycle" holds that new technologies go through a period of inflated expectations, disillusionment, and eventual productive usage. But with SOA, it seems the hype just won’t quit.

For me, the final straw came when attending two vendor presentations on application performance, where the logo for their new marketing campaign, emblazoned in the corner of each slide, proclaimed “Smart SOA.” The mind reels. What do JVM tuning and distributed caching have to do with service-oriented architecture?

Naught that I can see. SOA has simply become the miracle food additive of the IT industry. Vendors are straining to enhance the length and breadth of their product lines with “SOA enablers”, the same way food producers are jacking “heart-healthy” fish-oil extracts into everything from lunchmeat to orange juice, promising a revolution in IT health.

Reading the trade pubs, you must admit that ESBs are vital to ramping up your SOA. And governance? Can’t do without it. Help you manage the new services development lifecycle? You’re covered. Rules engines? Ready to fit your SOA. Metadata management? Check. Complex event processing? Check. And mashups? Hold on... those are now “enterprise” mashups, SOA’s killer app.

Do all these technologies actually enable service-oriented architectures? Let me allow Burton Group SOA maven Anne Thomas Manes to answer that:


It has become clear to me that SOA is not working in most organizations. … I've talked to many companies that have implemented stunningly beautiful SOA infrastructures that support managed communications using virtualized proxies and dynamic bindings. They've deployed the best technology the industry has to offer -- including registries, repositories, SOA management, XML gateways, and even the occasional ESB. Many have set up knowledge bases, best practices, guidance frameworks, and governance processes. And yet these SOA initiatives invariably stall out. The techies just can't sell SOA to the business. They have yet to demonstrate how all this infrastructure yields any business value.

For IT initiatives to make this level of investment and still not pan out shows an unsettling disregard for old-fashioned principles like clearly defined problems and rigorously worded requirements. In the case of SOA, we are hobbled from the start with a poor problem statement. Most are variations on the same theme. The one from Wikipedia, culled from several sources, will stand in as well as any:

Service-oriented architecture (SOA) is a method for systems development and integration where functionality is grouped around business processes and packaged as interoperable services. SOA also describes IT infrastructure which allows different applications to exchange data with one another as they participate in business processes. The aim is a loose coupling of services with operating systems, programming languages and other technologies which underlie applications. SOA separates functions into distinct units, or services, which are made accessible over a network in order that they can be combined and reused in the production of business applications.

While technically accurate, the wording does little to help either technologists or business users understand when SOA should be used, what benefits it brings, and how its adoption impacts an organization.

To its credit, the article (and most resources on the subject) go on to say that SOA “unifies business processes by structuring large applications as an ad hoc collection of smaller modules called services” and “new applications built from a mix of services from the global pool exhibit greater flexibility and uniformity”, et cetera. But judging from the experiences reported by Burton Group, these gains are not clearly understood, nor does use of supporting technologies guarantee them.

Improving the definition

I find it helpful to explain SOA, not as a standalone, abstruse technical concept as above, but as a small delta from knowledge that is familiar to both businesspeople and technologists. If SOA is new, if it is a step forwards from the way most development shops work, then what is that way called, where are we now? It’s product-oriented architecture, or POA, and the evolution from one to the other is straightforward.

A bit of history: Prior to the client / server era, if you were to take a 50,000-foot view of application architecture, it would not look especially interesting. There was only one tier, the mainframe, and everything lived there:


With the desktop computing explosion in the 1980s, it became de rigueur to move the UI and a good chunk of business logic to a box that cost less, was easier to program and administer, and could provide users with richer interaction:


Came the Web in the 1990s, and abruptly all that capability on the client became a competitive liability. The web allowed companies to transact business via any desktop, anywhere, not just those that could accept a custom install. So the client tier split again, with the bulk of product software moving back to a new server tier for the web.


(Here I’ve renamed the original Server tier as the “Data” tier – this is a stand-in for databases, mainframes, any repository of customer information.)

This is the current state of most product-oriented architectures. There are other intermediaries like firewalls, routers and middleware, but by and large, this is where the assets of a business product reside.

It ought to be far enough. Managing applications is difficult enough without splitting them into progressively more pieces. But in large enterprises and organizations serving diverse markets, it isn’t enough.

Two things happen: one, multiple products are built atop the same data to serve different customers and channels, often on different platforms:


Two, as the organization grows, responsibility is partitioned, and new data providers arise, a product must draw from many data sources:


Often both occur simultaneously. Over time, duplication of work appears: the same data integration, reconciliation, and business logic is being written for multiple channels. This is especially hazardous when independent applications have direct dependencies on multiple databases; as Neal Ford noted, what you essentially have is one large application with UI partitioned across product groups, all of which much regression test when the database changes.

A service tier helps with both situations. It hosts platform-independent access to common business logic on behalf of many channel products, and provides a measure of insulation to applications that do not require direct data access.


I’ve settled on the terms Client, Channel, Service and Data, but they go by many names. Herzum and Sims use User, Workspace, Enterprise and Resource. A Forrester brief on N-tier uses Interface, Interaction / Service Composition, Business Logic, Data. Various J2EE references call them Client, Web, EJB and EIS (hmm, no conflict of interest there.) I’ve heard Client, Presentation, Logic, Database; Client, Web, Service, Database; still more.

In each viewpoint the role of the new tier is roughly the same, and the evolutionary view suggests a much simpler, more business-oriented definition of SOA:

Service-oriented architecture is the separation of business processes from business products in order to enable more rapid and cost-effective reuse.

SOA is not some dramatic departure from established practice; it is a natural, emergent property of distributed applications. It says you can get more value for your development dollar by investing in a common base of capabilities accessible from multiple products and platforms.

Pitfalls in practice

While the conceptual evolution from POA to SOA is straightforward, the organizational evolution is not – and this is why SOA so often falls down. Here are some common obstacles faced in SOA adoption:
  • In counterpoint to the tired mantra, “IT must be aligned with the business”, services are not aligned with the business, that is, not with business unit product groups. They are aligned with business processes that potentially cross business units.
  • Requirements, funding / ROI models and executive sponsorship are historically project-oriented, and this model is what your oldest, most senior business and IT managers understand. The end result of a product development effort is something users can see and touch. Services are seen as infrastructure because their primary audience is application developers – and infrastructure is always under relentless cost pressure.
  • Development is divided between teams that provide common assets to product owners, and teams that actually build products. This demands that product developers cede a significant degree of control to service owners, leading to turf wars. SOA champions must be prepared to deal with these cultural issues.
  • Without adequate governance, it is easy to build services that only address the needs of individual channel products or data providers. This gives rise to JaBoWS (Just a Bunch of Web Services), where SOAP or some other protocol is used simply as wire format, with no attention paid to service modeling, interface design, and limiting redundancy.
When you need it

Deciding where you need SOA is not rocket science. The core requirement is to provide business process functionality to a diverse set of consumers, both end users and other applications. If that isn’t the case, SOA should be viewed skeptically; adding more moving parts will raise development and maintenance costs and may not offer meaningful return on investment.

It’s also not hard to tell the difference between adopting SOA and just using SOAP (and ESBs, and repositories, and rules engines, et cetera.) With SOA, your development is split across channel product initiatives and supporting service teams, with the latter taking a healthy portion of project funding and engineering talent. There are governance structures in place to drive consolidation onto common services. Executive sponsorship is rock-solid, and finance is on board with cost and ROI models for service projects that demonstrate clear long-term value to the business.

(Disclaimer: The above opinions are mine alone and do not necessarily represent the views of current or former employers.)

The Craftsman's Advantage

Monday, September 8, 2008

What a presumptuous name for a blog.

No, it isn't an attempt at solidarity with people who sweat for a living. And "Architect" is just the term HR departments reach for when they run out of lofty prefixes for "Engineer" -- a title that doesn't seem to bother some very distinguished individuals at (say) Sun and IBM.

With "Architect" too often comes the mandate that Thou Shalt Stop Coding, having at last risen above the mass of mere craftsmen. I still get asked, "You write code? Aren't you a [title deleted] of Architecture?" And the look that suggests I am indulging some unsavory juvenile pursuit, like zapping ants with a magnifying glass. (Actually, I used a chemistry set. Higher kill ratio.)

Code is the fundamental tool of our trade, and there's much to be said for attaining, and retaining, the status of craftsman (or craftsperson, if you're that P-C.) Which explains the "blue-collar" bit. It comes from a project post-mortem some years ago, at which I had the good fortune to be consulting, rather than sitting in the stocks.

Among other things, we found a distressing lack of technical leaders with practical knowledge, people who could think strategically, communicate with senior management, run teams, and still keep their hands dirty -- that is, maintain key technical skills that would allow them to know, not just believe, whether a project would succeed. "Craftsmen. Blue-collar types," someone said. Another: "Yeah, blue-collar architects!" Grins all around.

Good term for it, I thought, and filed it away, to soon forget in the frenzy of week-to-week.

It came to mind again when my wife and I were having renovations done. Adam and Bob (not their real names), our architect and builder, had long since, er, moved up the ladder from individual contributor, but I was struck by how completely in touch they were with "real work." As I watched them in action on site visits, and eavesdropped on abstruse chatter about soffits, cantilevers, load-bearing beams and whatnot, I realized the difficult relationship we see between developers and architecture astronauts was not there.

The reason? Adam and Bob weren't guessing. The project didn't have a "probability of success." Their blueprints and plans were as solid as the concrete foundation they had poured the last fall. They knew how to build the addition on our house, could see every step in their heads and even do it themselves if they chose, because they had done it before. And as their trade advanced over the years, with new tools and materials and techniques replacing the old, they had kept up.

That same commitment to craftsmanship creates a different sort of software architect as well. Being able to design and build confers a more nuanced, more credible perspective on

  • When REST is appropriate and when WS-* is needed
  • When to cross the line from Ruby on Rails to JEE or .NET -- and which to choose
  • When SOA is a wise investment and when it is a waste of time and money
  • Where caching should go in your daringly innovative N-tier solution, to keep it from sucking mud
  • Whether your outsourcing partner is writing quality code or creating maintenance headaches
  • When to take a calculated risk on an alternate persistence approach
  • Where that shiny new middleware the vendor is pitching fits in your messaging infrastructure
  • When a box-and-arrow diagram is geek line art, and when it has a workable implementation behind it
  • Whether a sharp job candidate is just talking a good game, or can actually get things done
  • When to add new languages and platforms to your app development strategy, and when to take them out
The non-craftsman is at a disadvantage because every technology is a black box. Its behaviors can only be understood from the outside. Its capabilities are conceptual, scrutinized perhaps but never experienced firsthand, with the immediacy and intimacy of actual practice. Its limitations, if not readily apparent, are a latent and immeasurable risk.

Maslow wrote, words to the effect: "When the only tool you have is a hammer, you tend to see every problem as a nail."

For software architecture, I would add: "When you've never actually used a hammer, you can't tell if a problem is really a nail."

(Disclaimer: The above opinions are mine alone and do not necessarily represent the views of current or former employers.)