Sunday, November 11, 2007

The Evil Mr. Singleton

In my not very humble opinion, the singleton pattern is the worst pattern ever, and the fact that it is discussed in many books that talk about patterns make people think that it's a good thing (which is a flawed thinking). To make matters worse, almost no pattern book talks about why singleton is bad for you. In a way the pattern books out are not unlike that of a phone book - you get a list of phone numbers, but it doesn't tell you the guy who owns the number likes to molest Flash developers and that you should avoid calling the number!

This reminds me of how beginners in OOP would always fall into a "how can I make my code fit into an inheritance model" state of mind.

There are a few reasons why you should never use singleton in your code, and most definitely not in your framework if you happen to write one. Here are some of the reasons I can think of off the top of my little head:

1) The syntax is hideous. There is no way to hide the fact that the object you are dealing with is a singleton.

2) The standard in naming a singleton is non-existent. Different people name the instance accessor differently. I have seen code that use getInstance(), getInst(), instance(), etc.

3) What should you do when you inherit a class that is a singleton?

4) If you are implement this in AS3, you have the additional problem of not being able to declare private constructor to prevent direct object instantiation on your class.

5) It makes your class less tolerant to change in requirements. What if one day someone would like to instantiate multiple instance of your class?

6) Making an object singleton is almost the same act as declaring a global variable. Anyone can access your object from anywhere in your application. This convenience allows you to create unnecessary coupling to your application more easily and irresponsibly.

7) Code that uses singleton must take care of destroying it or resetting it with a custom destroy method where appropriate. For example, if you are implementing a Restart feature for your game, you want to make sure you are getting a brand new copy of the singleton object whenever the game restarted.

8) Most importantly, enforcing the single-ness should not be done at the object level (especially for the ones that can be used across multiple applications). This is inherently a policy-based issue, and should be dealt at the application level (through the use of a policy-based class or passing your objects around), not at the object level.

I sincerely hope you will think twice before you start creating your next singleton. Remember, no one wants to be single forever!

Friday, November 02, 2007

Cool tool for double monitor -- ultramon
http://www.realtimesoft.com/ultramon/

Came across a pretty cool way of rendering a 3D sphere on Paul Ortchanian's website today.

Click here to see the 3D sphere in action. Paul is very generous in sharing his work, you can see the full source code for 3D sphere on his site.

Let's jump in and figure out how Paul renders the 3D sphere.

outer loop with i going from -180 to 180
inner loop with j going from -180 to 180
_x = _path.centerX + Math.cos(i) * Math.cos(j)*_path.FL;
_y = _path.centerY + Math.cos(i) * Math.sin(j)*_path.FL;
inner loop end
out loop end


Let's see what the code in the inner loop and see what it is trying to do.
Assume for a sec the center is located at (0, 0), the location is now
_x = Math.cos(i) * Math.cos(j)*_path.FL;
_y = Math.cos(i) * Math.sin(j)*_path.FL;

As you know from high school math, you can draw a circle parametrically by using
x = radius * Math.cos(theta)
y = radius * Math.sin(theta)

So the above equation is essentially:
_x = Math.cos(i) * Math.cos(j)* radius;
_y = Math.cos(i) * Math.sin(j)* radius;

Notice the differing term between _x and _y is Math.cos(j) and Math.sin(j), which is responsible for drawing a circle. The Math.cos(i) term oscillates from 1 to -1 and back, in effect this creates a series of concentric circles by shrinking the radius of the circle from "radius" to a fraction of it (and back). All it takes now is to vary z from -1 to 1 for each circle using Math.sin or Math.cos and you have a 3D sphere!