Monday, November 07, 2005

Anti-patterns for SOA: Part Two

Three general rules for service granularity and redundancy

I recently made a blog entry about “anti-patterns” for SOA. This is funny since I never took the time to define either "SOA" or “anti-patterns” at the beginning of the blog which lead to almost everyone reading it walking away with a different opinion. I say funny because I am the sort of person who finds that type of thing amusing ;-)

Okay – seriously, before I continue, I would like to put some definitions around both of these. For SOA, I will rely on the OASIS Service Oriented Architecture Reference Model Technical Committee’s work to develop a Reference Model for SOA. While only an editors’ draft at this time, the basic premise is that SOA is an architectural paradigm or simply stated – a way of viewing/doing things that center’s around the concept of a service. Revision 10 is coming out soon.
http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=soa-rm

SOA definitions are like a tush. Everyone has one. Anti-pattern definitions are similar. To lexically scope the rest of this blog, I will rely on the following definition introduced by Hayes McCormick, a lead engineer from Mitre:

“Anti patterns are negative patterns that present more problems that they produce”
http://www.antipatterns.com/briefing/sld003.htm

Hays also compares various types of anti-patterns. In IT, anti pattern examples may be the god class ( one large class that does everything), spaghetti code (procedural and un-ordered/unstructured), Design by Committee (always problematic) and those of you who use vi instead of emacs or pico (miscreants – you know who you are!!). Social anti-patterns include terrorism, pyromania, drug abuse and those or you who use vi instead or emacs of pico.

Rule 1: Granularity is in the eye of the beholder.

The question of service granularity seems to be a pervasive and confusing topic. Someone recently told me that an SOA with ten million services is probably a bad practice since it has too large a number of services and hence is hard to manage. I argued that number of services as a sole metric for whether or not SOA is implemented correctly is not a good metric given that it is subjective to the eye of the beholder. The point is that the rationalization for these things is not always obvious to the viewer.

Case in point? How about the Internet. The internet has over ten million individual services yet each of those services have a unique and valid function, at least to the owners of the content and those wishing to retrieve it. So look at this in terms of granularity. Should clusters of those services be bundled together? No. You are reading this blog which aggregates a few things (my posts plus thousands of comments calling for my banishment for heresy), however I will argue that IMO this blog should remain its’ own service.

If someone also owned a distributed grid computing network, they may wish to allow consumers to make leases to individual nodes via services. This means that each node in the cluster would have at least one service. The alternative is to implement an uber-service that then locates and leases the appropriate node on the cluster on behalf of the consumer and forces the consumer to remain agnostic with respect to the physical contract to the cluster node. So which is valid? Well, both. There are advantages to doing it each way.

So how far could you take the granularity/number of services concept before it becomes a legitimate anti-pattern? In J2EE many have made assertions about patterns and anti-patterns. The issue of granularity is measured by java programmers in terms of what they deem efficient or justifiable based on expected overhead. Puneet M. Sangal wrote:

“Accessing Fine-grained EJB Interfaces

Marshaling and unmarshalling data involved in a remote call across the network can cause major time latency in applications. Latency can also occur due to multiple remote calls. Based on the needs on the application, the solution might involve redesigning the EJBs, but if that's not the case, servlets should not remotely access an EJB entity via a fine-grained API. If the EJB's expose both fine and coarse-grained APIs then servlets should use single calls to the coarse-grained API in preference to making multiple calls to the fine-grained methods.”


Is this view justified? IMO, it gives us hints about some concepts upon which to base our decisions.

Convoluted SOA Contest Winning Idea?

Let’s take this to an extreme case. Imagine you wanted to render a raster graphic of some new platform. Let’s assume that the native format for the graphic returned a large hash of pixel values in Hex format. I will use text to make this easy to understand:

1, 1, #C0C0FF //pixel located at quadrant 1 from top, 1 from left, color is Hex #C0C0FF
1, 2, #C0C0C0
1, 3, #FFFFFF
Etc.

Now imagine that each pixel’s value had to be parameterized to web service call that would return the Hex value in RGB values. We can make this more granular by forcing the consumer to call a different service for each Hex value. Accordingly, the service endpoints would be http://www.domain-example.com:port/[hex_value]/ws

If you sent in #FFFFFF, the response would be rgb(255,255,255) which would render white. It is possible to make rendering software for your new raster graphic format make one service call for each pixel in the image.

I probably don’t have to tell you that this is a bad idea. It is very black and white (no irony intended) however there are other examples that are less ambiguous.

Rule 2: It is probably not possible to write a rule for granularity that is applicable to all situations.

For the record, the preceding idea was not original, it is merely a new twist on an old ploy to make a picture using an HTML table with hundreds of rows and columns, each having its’ own background color. Collectively, the table cells being rendered in an HTML client application would look like a picture. Hey – maybe we could produce that table by linking up the results of all the service calls……? Somebody shoot me now!!

In the preceding case, it would have made sense to call a single service that returned a large lookup table for all values, then simply iterate each Hex value against that for the corresponding value locally. My gut instinct would have been to architect it this way, but others may object (for various and perhaps legitimate reasons).

There are several questions that I will pose to you on this subject, interspersed with my answers. YAMMV (Your actual mileage may vary):

1. Should service calls be used in places where the overhead of incurring them exceeds the resources required to enable the functionality locally?

[Duane]: My gut reaction is that this is a consideration but will not always be the largest factor in the equation.

2. Would it be prudent to state that the call to the service should be coded in less lines that it would take to reproduce the functionality locally. For example, making a call to multiply two numbers together may take 25 lines of code in Java, including wrapping it in a “try/catch” construct. Doesn’t it always make more sense to simply write:

int var1;
int var2;
int result;
try {
result = var1 * var2;
}
catch (Exception e) {
//do something with error here…
}

[Duane]: Many programmers will probably not make remote calls for simple functions they can easily write. I am not sure if any rule can be made from this.

3. Is there any chance that “catch all” rules can be made to determine whether or not services are too granular? Consider the fact that some programming languages allow for sentences to be of type “String” and also allow them to be treated as an array of chars.
[Duane]: I do not believe this will be possible given we all tend to look at problems form different aspects.

4. If any of these rules are violated, is the thing still SOA?

[Duane]: SOA is SOA, whether good or bad design.


All of this is dependent upon your own views and principles.

I started thinking about this in terms of how other related efforts handle this. The first thing that struck me is the use of inheritance in object oriented programming has a strong effect on whether or not you use a local method or make a remote call. For example, imagine the following example as a class hierarchy.




If you need to do a multiplication operation on two or more integers, you would logically use the Calculus class. If you are writing a new class, you would import the Calculus class then call the multiply() method and feed it parameters. This would return a result. Importing the class gives you access to all the methods that class has.

It would be highly illogical to make a remote procedure call to another class for some functionality your imported class already possesses such as the multiply() method.

You will notice that in the hierarchy I established above, there are two methods on the language side that are very similar – WriteBookReport() in the English Literature class and writeReport() in the Grammar class. This illustrates another problem that exists within SOA – the number of similar or overlapping services. This has also been raised as a possible anti-pattern of SOA by a number of people.

In this case, the designer of the overall programming language would have the ability to re-architect the class hierarchy to form a more generic operation that may be called “writeReport()” and take a parameter of reportType (which might have a value of “book report” in certain instances).

This often has not been addressed within the context of SOA. class hierarchies are commonplace in every modern language. Service classification hierarchies are not as common. This may be an interesting thing to look at.

Conceptually, it the writeReport() operation the same as the writeBookReport() operation? This depends upon your perspective on the problem and the granularity of which you examine the operation.

A simple table with some generic aspects highlighted seems to indicate that the two operations are the same:



The two operations seem pretty similar from this perspective. Of course, when you examine other aspects, this starts to fall apart.



Okay – so this example was a little daft. Let’s look at a more relevant issue. Is an HTTP get() different from an HTTP post()? The patterns are both the same. You marshall a message into text and route it over the internet using an established protocol. It reaches a service which then evaluates the message and forms a response message which is then routed back to the sender. They both do this. So do the HTTP put(), delete() and other operations. Where they differ in functionality is not at the wire level, it is at the conceptual or real world effect level. This is an important consideration for SOA. What is the real world effect of invoking the service.

Rule 3: Duplication of Services is in the eye of the beholder.

Conclusion:

Alongside the issue of service granularity, we have a similar issue of duplication of services. Both of these issues are probably beyond some form of an immediate “best practices” guide that is applicable in all situations.

What do you think?

3 comments:

  1. I like the post, because it's essentially a set of meta-anti-patterns for SOA: things you shouldn't do if you're trying to tell people how to build SOAs. But that's because I find that kind of thing funny.

    I largely agree with you on the topic of SOA, too; I especially like the base statement "if you're not defining your system in terms of its user-facing operations, you're not defining a service-oriented architecture". It's one that's often lost on people, I think.

    ReplyDelete
  2. for some reason the link to apfSOA part 1 is broken.

    one weird weird behaviour i never saw before. i am using Firefox, but when i click on the link i go straight to Microsoft home page... i shit you not.

    also the link from my blog to part 1 is broken, which wont help send traffic your way.

    ReplyDelete
  3. My comments:
    1. Rule 1: Granularity is in the eye of the beholder.

    [RADHA]: Qualitatively True. But still some measurement guidelines can be given as akin to granularity definition in system software for Hard and Soft Real Time systems.

    Rule 2: It is probably not possible to write a rule for granularity that is applicable to all situations.

    There are several questions that I will pose to you on this subject, interspersed with my answers. YAMMV (Your actual mileage may vary):

    1. Should service calls be used in places where the overhead of incurring them exceeds the resources required to enable the functionality locally?

    [Duane]: My gut reaction is that this is a consideration but will not always be the largest factor in the equation.

    [RADHA]:. But how do we measure this overhead at the time of designing the service? Mere Line of code measurement is not a right indication.
    It also depends on the type of target processor the system runs on.

    2. Would it be prudent to state that the call to the service should be coded in less lines that it would take to reproduce the functionality locally. For example, making a call to multiply two numbers together may take 25 lines of code in Java, including wrapping it in a “try/catch”
    construct. Doesn’t it always make more sense to simply write:

    int var1;
    int var2;
    int result;
    try {
    result = var1 * var2;
    }
    catch (Exception e) {
    //do something with error here…
    }

    [Duane]: Many programmers will probably not make remote calls for simple functions they can easily write. I am not sure if any rule can be made from this.

    [Radha]: Again complexity of the code could be a factor. For example if complex mathematical operations are part of the functons say exponential,logarathimic, this may be better classified as a service even if the call takes longer lines than being coded locally. Math Coprocessors practiced in the firmware an example.

    3. Is there any chance that “catch all” rules can be made to determine whether or not services are too granular? Consider the fact that some programming languages allow for sentences to be of type “String” and also allow them to be treated as an array of chars.
    [Duane]: I do not believe this will be possible given we all tend to look at problems form different aspects.

    4. If any of these rules are violated, is the thing still SOA?

    [Duane]: SOA is SOA, whether good or bad design.
    [RADHA]: Yes as long as it does not affect the chain of services.

    Rule 3: Duplication of Services is in the eye of the beholder.

    Conclusion:
    Alongside the issue of service granularity, we have a similar issue of duplication of services. Both of these issues are probably beyond some form of an immediate “best practices” guide that is applicable in all situations.
    [RADHA]: Service classification hierrachy may solve this problem to a
    great extent.

    ReplyDelete

Do not spam this blog! Google and Yahoo DO NOT follow comment links for SEO. If you post an unrelated link advertising a company or service, you will be reported immediately for spam and your link deleted within 30 minutes. If you want to sponsor a post, please let us know by reaching out to duane dot nickull at gmail dot com.