Saturday, February 02, 2008

Prototype

Name : Prototype
Context : Obtain a copy
Consequences :
1)Add remove products at runtime
2)Specify new objects by varying value or structure
3)Reduced Subclassing
4)Configure an application with class dynamically
Examples
Anything implementing clone(),
Class

Factory method

Name : Factory Method
Context : Hide the implementation class but defer the instantiation to subclass
Consequence
a) Provides hooks for subclass
Examples
Calendar.getInstance()
Connection conn = java.sql.DriverManager.getConnection(uri, name, password);

Friday, February 01, 2008

Abstract Factory

Name : Abstract Factory
Context : Creating Related family of objects
Example: Toolkit(awt)
java.sql.Connection (sort of creates Statements and PreparedStatements and CallableStatements where each is specific to the database)
Consequence
1) Exchange Product Families
2) Supporting new kinds of products
3) Factories are normally singletons! But they need not be.
4)Note that every factory must support every type of object to be created. This is sometimes problematic.

Singleton (Creational)

Name : Singleton
Comment : Probably the best known (atleast if you go by answers you get in interviews to the question 'Patterns you have used') of the design patterns and probably one of the text book cases of people ignoring understand the context and understand the consequences when it comes to this pattern
Context : Need only 1(or a fixed or controllable number of instances) (e.g. memory consumption , or heavy initialization like reading a file,a requirement - there is only one Neo, a pre java 1.5 enum such that == can be used )
Examples : Single Instance (java.awt.Toolkit, Inspector)
Consequences :
a) Controlled access to state
b) Permits a variable number of instances (e.g. access to any object pool)!
c) Watch out for real world multiple managed servers, clusters etc(older versions of Expresso framework used an in memory primary key generator as an incremented singleton - no use in a cluster. Real world naive code that uses a timestamp plus ip address as unique key through a singleton)
d) Watch out for synchronized access for loading the singleton, thread safety, shared state.
e) Watch out for serializable (might break singletoness if you dont follow effective java)
f) Watch out for static block errors during initialization(if initialising eagerly). Will cause NoClassDefFoundErrors.
g) Watch out for being unable to reset a singleton (e.g. a singleton that reads a file and stores it.If your not careful , changing the file needs a bounce of the server)
h) Watch out for singletonitis. i.e. Making classes singleton even when there is no shared state, no performance or initialisation penalty.
i) Watch out for problems testing the singleton

With all the Watch out's is this pattern worth the trouble? read the context!

Design Patterns Course

The following series of posts deal with a design pattern course I conducted for a few colleagues of my team who insisted that I knew enough to conduct such a course(I don't). One of the problems I had faced while attending the design patterns course conducted by probably the best Technical Manager I've worked under (Homi Bharda) was that practical examples were hard to come by, where you could see the usefullness and though the Design patterns book by Erich Gamma did point to some examples they almost always dealt with GUI heavy , stateful , highly object oriented programs while at that stage I dealt with mostly stateless CRUD web based applications.
I resolved that any course I took would show practical examples and what better example than the Java API which was quite familiar to my colleagues. I also had a lot of problem differentiating between patterns. Some of the Factory patterns looked alike. Some of the patterns like Command and Strategy looked alike. I resolved to have some comparisons at least.

What these notes dont have is my bitterly cynical comments e.g. of people who code such that all their classes have a suffix which is pattern e.g. ObjectCommand uses an ObjectFacade uses an ObjectFactory creates an ObjectService which uses an ObjectDAO and returns an ObjectAdapter which wraps an ObjectDecorator which wraps a ObjectDTO (Disclaimer I have done this too). This literally is the developer's cry look Im a designer , I use patterns , I even know their names! But ask them Give me some examples of design patterns in the Java SDK and we have a) Blank Stares b) Singleton c) A very very few Decorator.
So anyway other than the above rant , very few cynical comments


General Notes
What is a pattern ?
A Name, A Recurring problem with context, A recommended Solution(or way ahead), Consequences and Alternatives
The bit a lot of people miss out is the Context and the Consequence. A pattern cannot be used irrespective of the context . This causes problems like 'Singletonitis'. A pattern always has some consequence. A pattern probably does have alternatives which are to be evaluated.
A pattern need not always be up front design, you can arrive at many patterns with a judicious use of refactoring and some simple principles notably DRY.
Patterns are also sometimes subsumed by the language or the platform (e.g. Factory in Visual Basic COM and Iterator in java) and some people refer to patterns as deficiency in the language / platform ( I dont agree!).
Anyone who does anything with Design Patterns has to refer to Erich Gamma's et al book , and thats what I have based this on including the organisation of the patterns as Creational, Behavioral and Structural. Its quite difficult for novices (like me) to differentiate what between what constitutes a behavioral or structural pattern so dont bother right now.
Also note that any Object oriented system has available to it the mechanisms of Polymorphism and Inheritance (Implementation of Interface). Therefore all diagrams of Design patterns will look similar in a lot of case. it is necessary to understand the nuance and differences and context.
And lastly in a web project , differentiate between building a framework and solving a problem at hand. Its very easy to get carried away and over engineer and its as easy to under engineer, and it's also simple to shout TDD, refactoring , agile. Ultimately experience is what you use to decide whether you need a pattern upfront or later, Refactor or not. And anyone who tells you otherwise is either a manager or a consultant.

Friday, January 25, 2008

Testing

You really appreciate the value of tests (especially regression) when you have to fix some code which is complex and is used in multiple places and you aren't sure of the various conditions under which it gets invoked (or even what the result should be). Unfortunately it is sometimes difficult to convince management. We asked and were denied initially anyway , for a separate environment to create and run tests. The separate environments were needed because of the extreme complexity of the business needed, in my opinion, an environment where the initial state is exactly known , otherwise there is no way to accurately predict the outcome of running time sensitive, old data sensitive scenarios. However the cost of maintaing said environment was deemed to be too high. Im not so sure. anyway we are getting an environment so yay, let the games begin.
It's also at time like these that you realise , how out of touch with reality , the TDD/Agile/ JUnit testing people that you see are , because they never seem to discuss anything but unit testing.
I cant see unit test's adding much value to the system I work in , but oh what wouldn't I give for a set of repeatable integration and functional tests.
Other than the really good Java Next Generation Testing book I havent seen the Testing books deal with real world stuff. (Did anyone else think that the Junit cookbook example of Money was representative of what people test in an automated way in real life)

So here are the things that make the testing complicated
a. The system run's on a cluster. Problems have been reported on the cluster , some of which have found to be environment related and some are code related. Would anything other than in container testing on representative environments find this out?. This deals directly with the people advocating 'mocking' interfaces, not running in container, having fast running tests etc.
b. One of the defects was caused when two unrelated processes ran at exactly the same time and on the same server of the cluster. The processes shared infrastructure code but were business wise and code wise unrelated. How would a test have found this out , other than sheer luck? Note that junit as a framework is really bad. Again this is not a complaint about JUnit, just that you dont see people discussing concurrent testing of unrelated data.
c. A complex Architecture. A portal sends data asynchronously (JMS) to a WLI system which has multiple processes , which in turn needs a lot of system data (histories) to perform calculations, makes its business decisions using a set of business rules which are User Configurable(using a totally different system) and then persists this data to a database.
Assuming you want to test that everything works end to end, is there any other way other than restoring the system to a known point in time(so you know what the out come should be?). The catch again is that running the same test on the exact same data might not still return the same results because the results are time sensitive (e.g. there is a different contract for 2007 as compared to 2008 so running the test in 2008 will give you different results).
d. The results depend on the sequence of tests. This isn't a code problem , this is exactly how the business works. Other than creating different data for different cases , this is difficult to solve. In addition you do want to also test what happens when a particular sequence of events occur ( a claim is in , it is paid, the cheque is sent, the claim is adjusted, a new check is sent , the first one is returned, now assert). How is it that the unit testing folks shout themselves hoarse that tests should be independent of each other. I know I know , what I have described isn't a unit test. But you see , the individual bits work. The sequence fails.
Oh I can go on. But there is an India v/s Australia cricket match. Go India!

Debugging

Due to circumstances beyond our control , we've had to take up fixing someone else's code. The business rules are complex (which means the code must be so). There are no existing tests (this is a consequence of both the complex rules and a complex architecture , the latter could be simplified if it were not for the fact that the project is years late). Now the TDD guys are probably jumping up and down at this stage , pointing out that the lack of tests is the reason why everything is so complex , just ignore them , we'll get to these folks later. The bottom line is there are no tests, we are trying to create some regression tests, that will take time , meanwhile there are still bugs to be resolved. I was assigned one of them.
It took me 2 hours to setup the environment . Ones a weblogic portal domain and Ones a weblogic integration domain. The build for the portal takes about 30 minutes after which weblogic workshop duly crashes. I have to point my servers to a configuration other than their default which needs me to mess around manually. It takes another hour to understand what the defect is. it takes some more time to verify that the tester is indeed right, the system is doing something wrong. It takes some time to identify the areas of code that are possibly the cause. it takes a couple of hours to understand the nuances in the mostly undocumented code.
I then have to go and ask another dev, whether the testers expected results are correct, and it turns out they aren't. There is a defect and what the system currently does is wrong , but what should the system do is undocumented and unknown. We could make a guess but this impacts other systems so we need them to confirm. A meeting is scheduled.
The meeting lasts 2 hours. Some issues are resolved, Some new ones are raised. Some have to be followed up with other people. Armed with some more knowledge I look through the code. I get a sudden inspiration, I test out two scenarios , it looks like I'm right.

The defect is fixed by modifying all of two lines of code. Total time to fix defect ? 1.5 days.