I'm writing a little sample for Silverlight 5 in Action. Part of
it involves a class which integrates with a 3d accelerometer sensor
on Windows. In order to use the accelerometer, I have to check to
see if elevated permissions is enabled before I go about
constructing objects which rely on COM automation. There's also a
fair bit of construction activity after that check to create the
actual sensor object and prepare the class for use.
There are three approaches to creating this object and
performing the initialization. All three have issues. Here they
are.
Code in the Constructor
It "feels" right to handle the permissions check in the
constructor. However, throwing exceptions from a constructor is
generally considered a bad… no, an EVIL practice. The code in this
example is the smallest, and tends to be the most easily understood
by other developers. Here's an example of what the code might look
like (don't get hung up on the specifics of the code itself, as it
happens to use the Native Extensions for Silverlight, but could be
any similar functionality) :
public class AccelerometerJoystick
{
private SensorManager _sensorManager = null;
private Sensor _accelerometer = null;
private PropertyKey _keyXGs = null;
private PropertyKey _keyYGs = null;
public AccelerometerJoystick()
{
if (Application.Current.HasElevatedPermissions)
{
_sensorManager = new SensorManager();
// do a bunch of other stuff to create a Sensor instance.
}
else
{
// throw an exception that says you need permissions
}
}
public void DoSomething()
{
// ...
}
}
The constructor exception issue is especially nasty if the
object is constructed in XAML. That's not my intent with this
class, but you never can know exactly how your class will be
used.
It's also nasty because your construction code needs to be in a
try/catch, which isn't always intuitive. Rightly or wrongly, many
folks put construction outside the try/catch block, and expect only
actual methods to throw exceptions.
Using an Initialize Pattern
Another approach is to use an initialize pattern. I've hated
this pattern since the day we started using it Visual Basic (4, I
think) when we had classes without real constructors. Basically,
this requires a two-step process. First, the caller creates an
instance of the object, then the caller calls the Initialize method
which performs the initialization and sets a flag. Because the
caller could forget to call Initialize, the code inside the class
needs to do a check against that flag (or an object being not null)
in every method.
public class AccelerometerJoystick
{
private SensorManager _sensorManager = null;
private Sensor _accelerometer = null;
private PropertyKey _keyXGs = null;
private PropertyKey _keyYGs = null;
private bool _initialized = false;
public AccelerometerJoystick()
{
// pretty empty
}
public void Initialize()
{
if (Application.Current.HasElevatedPermissions)
{
_sensorManager = new SensorManager();
// do a bunch of other stuff to create a Sensor instance.
_initialized = true;
}
else
{
// throw an exception that says you need permissions
}
}
public void DoSomething()
{
if (_initialized)
{
// ...
}
else
{
// throw exception saying you're not initialized
}
}
}
For the record, I absolutely LOATHE this pattern. I hate that
the caller has to have a regular construction statement followed by
an Initialize statement.
You can also use a lazy initialize pattern where instead of the
caller calling Initialize, you check in each method and perform the
initialization if not already initialized. I'm not a big fan of
this approach either.
Using a Simple Factory Pattern
Yet another option is to use a factory pattern. I think factory
patterns tend to be overused. However, like the Initialize pattern,
this is something we've used since the old VB days when we didn't
actually have constructors. It's ok in that you don't have to
remember to call an initialize method, and don't need all those
checks in your code, but you can still get an exception on the
actual construction.
With this approach, you need a private constructor and a public
static method to handle the construction.
public class AccelerometerJoystick
{
private SensorManager _sensorManager = null;
private Sensor _accelerometer = null;
private PropertyKey _keyXGs = null;
private PropertyKey _keyYGs = null;
private AccelerometerJoystick()
{
// pretty empty, but private
}
public static AccelerometerJoystick Create()
{
if (Application.Current.HasElevatedPermissions)
{
var joy = new AccelerometerJoystick();
joy._sensorManager = new SensorManager();
// do a bunch of other stuff to create a Sensor instance.
return joy;
}
else
{
// throw an exception that says you need permissions
}
}
public void DoSomething()
{
}
}
This is more convoluted, especially when compared to the
constructor approach. It also has a habit of becoming the big
sledgehammer you use throughout your code, and I can't stand that.
IMHO, this approach is probably the safest, but it still doesn't
smell quite right to me.
What would you do, and why?