Among the reactions I got for my previous post on the Singleton pattern in .NET were a couple that talked about the design rationale behind the solution I posted:

Adi Avnit posted on the risk of using a "generic singleton":
"However, there is one possible pitfall to this approach, as it makes this code possible:
Singleton obj = Singleton.Instance;
MyClass obj2 = new MyClass();

While I personally like the idea of having the freedom to use the same class in two different ways throughout the application, I know some people like their Singletons - well, single.
On the other hand, if you write a class from the start as a Singleton this is not an issue.

There is an inherit risk in decoupling a class from it's expected behavior, so take this into consideration before using this pattern."

And Cade Roux wrote in a comment:
"don't believe discoverability was a motivation for Singleton. The purpose was to ensure only one instance existed (a print spooler, a file system). You can get discoverability through the technique you explain but the primary purpose of singleton was a pattern of prohibition - to stop a programmer doing something they shouldn't do by accident by enforcing the primary goals of single point of access.

It is more than a global, and the OP, while comparing them to globals, does not acknowledge that this solves many of the problems which made "global" a 4-letter word. Knee-jerk reaction against globals is not healthy once you've mitigated their drawbacks.

It is true that usage of singleton can be misguided and cause coupling - which is why you need to ensure that the usage of the pattern matches the motivation in the first place.

This is a key point of design patterns which Alexander should have made clear in http://en.wikipedia.org/wiki/N...is_of_Form - the pattern is a result of a resolution of system of forces. It only satisfies that system - moving it to another different system will result in poor fitness. "
I guess that's a good opportunity  to talk about design issues regarding Design Patterns in general and the GoF ones in particular.

Aristotle Pagaltzis
noted (in a comment on Cedric's blog) that
"design patterns are a sign of a deficiency of a language for the purpose that the design pattern addresses. In other words, the Visitor pattern used in Java points to the fact that Java is deficient in terms of list processing: the `map` and `filter` constructs need to be emulated with lengthy OO incantations."
In other words Concrete patterns* (like GoF's) are tied to implementation which means that the implementation language is  part of their "context". Thus when you come to apply a pattern in a different language you need to consider the language in use and make sure that
  1. The pattern is needed
  2. The solution in the pattern is the best one for the language.
Let's look at a few examples.
If we take the Visitor pattern mentioned above - The intent of the visitor pattern is to "represent an operation to be performed on the elements of an object structure without changing the classes of the elements". In .NET 3.5 you can do that with the use of LINQ (to find relevant items) and extension methods (to add external functionality) - same intent, completely different implementation.

In the case of the Singleton pattern (mentioned in the previous post). The intent is to "Ensure a class only has one instance, and provide a global point of access to it". An implementation using templates (or generics) is superior since it provides the same intent but also adds better compliance with the Single Responsibility Principle. While it is possible to create the class as a non-singleton on the one hand it solves the multi-threading issue in one place preventing both duplication of code and mistakes (again this can be especially important in non-forgiving environments like C++). It also lets you (not in the implementation I provided) add flexibility and e.g. let singletons die and (if needed) resurrect themselves etc. Note that even if you are not convinced that using generics is better, there's no doubt that using .NET's thread-safe static readonly variable (public static readonly MySingleton = new MySingleton();)  is a much simpler solution than the GoF one and again, answers the original intent with a different solution.

Another example would be the Template method pattern. The idea behind the template method is to support the Open closed principle (classes should be open for extension but closed for modification) or as the GoF defines the intent:
"Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template method lets subclasses redefine certain steps of an algorithm without changing the algorithm strucuture"
.NET 3.5 supports the notion of Generic Delegates so you can define functions as parameters and pass them along. This is a better implementation than the template method as now you don't have to subclass when you want to extend an algorithm you can just pass a function that matches the signature
e.g.
    class Program
    {
        static void Main(string[] args)
        {
            var alg = new Algorithm();
            alg.DoSomething(Funky);
        }

        static bool Funky(string value)
        {
            return value == "somevalue";
        }
    }


    class Algorithm
    {
        public void DoSomething(Func<string,bool>CanGoForward)
        {
            string someVariable = "somevalue";

            if (null!=CanGoForward && CanGoForward(someVariable))
            {
                //do one step
            }
            // whatever
        }
    }


You should note that this "refactoring to fit the language" phenomena isn't limited to GoF patterns (or .NET :)) , for instance you can consider the use (or lack thereof) of Dependency Injection in languages such as Ruby which I wrote about a few months ago.

To sum up - when you talk about design patterns you need to consider the implementation language, design pattern deal with deficiencies in the language and different languages have different deficiencies and may have better solutions to the problems solved by the patterns



* As opposed to architectural patterns which are more abstract and thus more reusable (e.g. Hohpe & Wolf Enterprise integration patterns, or Martin fowler Enterprise Architecture patterns)


 
Tags: .NET | Design | OO

Simon @ CodingTheArchitcture recently asked "How big is your software architecture document? (and who reads this stuff anyway?)"
He notes that in a UG meeting most of the attendees has SADs that were more than 50 pages long.
It would probably not be too surprising if I say than in my opinion the answer is that it depends. Reflecting back on some of my past projects I had SADs that varied in range from a 200+ "write-only"* document to a less than 10 pages lean document. And the sizes match the intended usage of the documents. for instance in the two extremes mentioned. The first case it was a huge mission critical project with a specific requirement from the customer to have an "official" SAD and it was written to satisfy some project milestone (PDR) . Where the second extreme is an agile project where the architecture document was a working document, written some 10 iterations into the development to highlight some of the emergent guidelines.

What is common to all the SADs I wrote (or was responsible to) is that they all tried to grasp the essence of the design, all used multiple viewpoints to describe the solution, all were focused on quality attributes and all explained the rationale behind the decisions.
  • If you drone endlessly with details you don't see the forest from the trees.
  • if you don't use multiple views - you are likely to miss important aspects of the solution
  • if you aren't focused on quality attributes that you are most likely documenting design and not architecture
  • and if you don't explain the rationale then the document doesn't have a lot of added value beyond the code itself
in any event, the important thing here is that when it comes to Software Architecture Documents "size doesn't matter" :). What matters is that the SAD satisfies the reason it was written for


*While this particular SAD was rather long it also had a section that helped potential readers find relevant chapters so that it can actually be usable, and not just as a"door stopper"

 
Tags: Software Architecture

Awhile ago I asked "who tests the test":
" One question I don't hear asked too much is "who tests the tests?" - after all we are writing all this additional code - if we write so many bugs in our production code that we need tests - what are the chances the test code is clean?"

I would add that this is especially true considering that the same person that writes the code also writes its unit tests

One answer I had was making sure to keep the triad of tests->code->acceptance tests. so that each two test the third. This is especially good since, usually, the acceptance/integration tests are not written by the developer who wrote the code.

One answer I got was that tests are usually simple enough to be self evident and when tests contain complex constructs you should probably test them as well.

Basically, tests can have two types of problems
  • Not testing the right thing
  • Not testing the thing right
Code+unit tests +acceptance seem to take care of the first type of problems. The claim that tests are simple should take care of the second type of problems.
However I think that it isn't always true, especially when it comes to using the tests for regression. consider for example, the following two incidents I had  where the the problems were actually with the tests:

1. We have a component that interacts with resources in different URIs, so when resources wake up they register themselves with that component. Resources register two URIs -> one for control and one for interactions. We've added a business rule that both URIs should be on the same host (naturally a new test for that was also added but that not the point) suddenly a bunch of the old tests started failing. Sure enough, I took a look at the new code, found a bug, fixed it, but the tests were still in the  red. In the end it turned out one of the Uris that is registered during the tests had an extra "L" (locallhost instead of localhost) so the tests failed with the new rule - as they should..

2. After writing a piece of code to "just work" it had to be made multi-threaded. I needed to write a test that would make sure the component can handle multiple concurrent requests. Sure, I thought, I'll just run few or even all of the other tests in parallel and be done with it. The only problem was that the other tests were written to be isolated (i.e. new instance per test) running them in parallel had no effect what-so-ever.

What can we do to help us locate problems and bugs with tests?

  • remeber that Test code is code - so as you write more tests you should also refine the tests design and refactor the code accordingly. For instance in the first example above, it was easier to diagnose the problem since the faulty setup was done by a single method used by alll the failing  tests (Single Responsibility Principle @ the method level).
  • Test-First - One of the reasons test-first is beneficial is because you can actually see the test fail before you implement the code to make it work. This helps you make sure that the test actually tests the behavior you want. When the code is already in place it is harder to make sure if the test works because of the change or not. In the second example running all the tests in parallel everything was still green, which triggered me to write specific tests for checking for multi-threading issues.
What do you do?



 
Tags: Design | TDD

Someone calling himself r r left the following comment on part IV of my series of posts on SOA definition:

"I keep trying to read this series on SOA unfortunately suffers from the same disease as the rest of literature on the subject. stays general to a comfortable level so it can't really be applied anywhere, tends to complicate things where is not clear if it's needed, and encourages philosophical debate on what ultimately is a business (and so concrete) requirement. Meanwhile the serious (IMO) issues stay untouched - how does one actually approach an integration project with functionality, performance and security in mind. Which should be the standards used (considering the tens of standards on WS out there). How granular should the WS be (I'm done with answers like "not too much, but enough", or "well, depends on your project"). "
Before I talk a little about the "serious issues" mentioned above - I want to point out that the point of this series of post, as stated in the first post is to take a formal / semi-academic look at SOA. I started these posts as a reaction to a comment that Pete Lacey left on my blog stating that my view of SOA (as published in "What is SOA anyway?") does not demonstrate that SOA is an  architectural style. I don't pretense that this is some fully thought out academic dissertation or anything but I do try to look at the architectural roots of SOA.

That said let's take a look at the more interesting parts of this comment. First, the thing that bothers me about this reaction is (what seems to me as) the quest for final and concrete recipes. For instance consider the comment on service granularity
"How granular should the WS be (I'm done with answers like "not too much, but enough", or "well, depends on your project"")
The problems is - it does depend! and if you forgive me taking another philosophical detour, if you try to provide a hard definition for a service granularity you get  something like the heap paradox - When you remove individual grains  from a heap of sand is it still a heap when one grain remains. So while it is obvious that hiding a complete system as a single service is wrong and that exposing every little object as a service is wrong (even though for some inexplicable reason Juval lowy seems to thing that the latter is good practice) it isn't really obvious when you get too granular.

Nevertheless it is not a pure guess either. You can use some guidelines and measure them against your specific project/system/enterprise needs. Personally The set of guidelines I use is based on the fallacies of distributed computing :
  1.  The network is reliable
  2.  Latency is zero
  3.  Bandwidth is infinite
  4.  The network is secure
  5.  Topology doesn't change
  6.  There is one administrator
  7.  Transport cost is zero
  8.  The network is homogeneous
Since a service edge is boundary which may (usually is ) be accessed remotely you need to think about the incoming and outgoing interactions of the service within the fallacies stated above. if the proper behavior of the service depends on one of the above there's probably something wrong.

Regarding the other questions (how do you approach a real system), well, if you pardon me for banging my own drum, that's exactly why I started to write my experience on these matters as patterns. for instance if we look at the saga pattern (one of the patters I published online). you'd see that it is talking about achieving distributed consensus in a transaction-like manner. I talk about the problems of using distributed transaction etc., offer an architectural solution (the saga ) and then discuss relevant technology issues (e.g. WS-BusinessActivity ) as well as its implication from quality attributes perspectives (Integrity and reliability). Nevertheless even these patterns aren't an end-all solution. different circumstances require different solutions
Both my previous job and my current one involves building a scalable solution on-top of algorithmic engines. In my previous job I  managed the construction of a biometric solution that allows using multiple biometrics. In my current job I manage the development of  a mobile visual search solution . Again, while on the surface both needs to get some data, run a few  algorithms and produce an answer. These systems have very different quality attributes. On the first system we had to handle very large databases, hundreds of queries, an emphasis on modifiability and security, the current one needs millions of queries, almost no database, low latencies and emphasis on usability.  These differences result in radically different solutions, with different services, different interactions , use of different patterns etc. There's no "one right answer" (tm)


 
Tags: PaperLnx | SOA | SOA Patterns | Software Architecture