Sunday, September 28, 2008

Baking the Abstract Factory Pattern

The abstract factory pattern is a common fixture of well designed code.  As useful as it is, it can be an annoying pattern because the scaffolding to implementation ratio is quite high.  It also breaks up code that most of the time should be together.  Other patterns that reach this level of usage often benefit from being baked into the language framework, so why not this pattern.

Let's look at a fairly basic implementation:

public interface ButtonFactory
{
Button CreateButton();
Button CreateButton(Control parent);
}

public interface Button
{
void Draw();
}

public class WinButtonFactory : ButtonFactory
{
public Button CreateButton() { return new WinButton(); }
public Button CreateButton(Control parent) { return new WinButton(parent); }
}

public class WinButton : Button
{
internal WinButton() { ... implementation ... }
internal WinButton() { ... implementation ... }

public void Draw() { ... implementation ... }
}

public class SampleUser
{
public void UseFactory()
{
ButtonFactory factory = new WinButtonFactory();
Button parent = factory.Create();
Button child = factory.Create(parent);
}
}


This is okay, but if we had a little syntax help:



public interface Button
{
Button();
Button(Control parent);
void Draw();
}

public class WinButton : Button
{
public WinButton() { ... implementation ... }
public WinButton() { ... implementation ... }

public void Draw() { ... implementation ... }
}

public class SampleUser
{
public void UseFactory()
{
Factory<Button> factory = WinButton.GetFactory<Button>();
Button parent = factory;
Button child = factory(parent);
}
}



That's a fair bit more succinct, and it also allows the definition of the "Create" to reside within the interface, making it much more obvious to consumers of the API the relationship between the factory and the interface.  The same is true for the implementation, where it's no longer necessary to either provide a workaround to the visibility issues that arise from having object initialization in a separate class.



Some might object on the basis that the use of the factory pattern extends beyond the example above, but those uses can still be accommodated:



public class ColoredButtonFactory : Factory<Button>
{
private Color _color;
private Factory<Button> _factory;
public ColoredButtonFactory(Color color, ButtonFactory factory);
{
_color = color;
_factory = factory;
}

public Button()
{
Button button = _factory();
button.Color = _color;
return button;
}
}



Which is equivalent to this implementation without language level factory support:



public class ColoredButtonFactory : ButtonFactory
{
private Color _color;
private ButtonFactory _factory;
public ColoredButtonFactory(Color color, ButtonFactory factory);
{
_color = color;
_factory = factory;
}

public Button CreateButton()
{
Button button = factory.CreateButton();
button.Color = _color;
return button;
}
}



An alternative (with pluses and minuses) the language level factory support would allow for is:



public class ColoredButtonFactory<TButton> : Factory<TButton>
where TButton : Button
{
private Color _color;
public ColoredButtonFactory(Color color);
{
_color = color;
}

public TButton()
{
TButton button = new TButton();
button.Color = _color;
return button;
}
}

Wednesday, September 24, 2008

deSleeper Beta 0.5

Another update to deSleeper finished up today.  I've been trying to make it a bit more user friendly.  I should have finished a bootstrapper but I got distracted by some other wants...  For example a much better way to get your credentials in and a way for you to wake up a system via host name (i.e. mypc.mycompaniesinternaldomainname.com). 

The catch to this second feature is that for most PCs it's only possible to resolve a host name to a MAC address while the computer is actually on.  What deSleeper does is store a cache of hostname/MAC address pairs so that it can do that resolution when the computer is off, but to make that work it has to search at least once to populate the cache.  So if you have your target machine on, send a wake up request with the client that will cache the hostname.  Then you can use the hostname with target off.  Since this is a new feature, might want to make sure you have the MAC address available just in case though.

Saturday, September 13, 2008

The end of the light bulb joke

Question: In 2020, how many kids will it take to change a light?

 

Answer: None, LED lights last 20 years so they'll be adults before one burns out.

Monday, September 08, 2008

deSleeper Beta 2 Released

I posted a new build of deSleeper to CodePlex last night.  I was interested in learning a bit more about WPF so I used some of that time to touch up the UI and neaten things up under the covers a bit.

deSleeper Wake Up Tab

Also, feature wise, I've added a tab to help you configure the "target" machine's network card driver to accept wake up requests.  You can do the same things through device manager and control panel, but this is a bit more convenient.  One note though, to support Wake-on-Lan requests from all power states (such as hibernate and power off) you still need to make sure the BIOS is properly configured.  The network card driver usually can't do anything more than make sure you can come out of a sleep state.

image

I still have a more plans for deSleeper, such as a distributed mesh system (this should allow you to take by hostname or IP, rather than MAC address), but I thought I'd mention 1E WakeUp I ran across recently that while it may cost a bit does appear to tackle the same issues as deSleeper.  If your a network admin with lots of computers to configure, I won't blame you for choosing 1E over deSleeper.  As long as you get your office setup to allow those hard working PCs have a good nights sleep, I'll be happy.

Should the U.S. drill "everywhere"?

My purist thinking side says, no, the places where the opportunity to drill remains restricted are a combination of costly to recover, dangerous to recover, and not very large anyhow.  I'd rather see the money spent on building solar panels, wind farms, battery cars, hybrid cars or even cellulosic biofuel than on oil platforms, deep water drilling, and all the complicated machinery necessary to keep the environmental effects of drilling obnoxious rather than disastrous.

My political compromising side says, drilling is dumb, but it's only a little bit dumb.  It's not as dumb as letting solar and wind tax credits expire, it's not as dumb as subsidizing the oil companies, it's not as dumb as driving an SUV, and it's certainly not as dumb as not investing in public transportation.  I also realize that a significant number of people not only fail to realize how dumb those other acts are, but think that drilling is the most brilliant idea ever conceived.  So I recognize an opportunity here, an opportunity to trade-in on the totally out of proportion enthusiasm drilling inspires in the opponents of public transportation and renewable energy.  It's not perfect, but that's what politics and compromise are.

My dark, sarcastic side goes further.  That part thinks, well maybe it's really important to allow the drilling, because if we do, it won't be more than 6 months later before the proponents of drilling realize how stupid they were to think it was the solution to the problem.  Sure, you have politicians who support drilling who say things like "drilling will not solve all of America's energy problems - as if we all didn't know that already", but among their supporters and colleagues individuals who really believe that is the solution, and that somehow it will take effect tomorrow too.  I'd like to burst their bubble just for spite.  Let em try and drill there way out and see the look on their faces when they finally realize 6 months to a year later, hey, it's gonna take 10 years, cost a lot and even then be no more than a drop in the bucket.