Here is an example of why I am looking for the interfaces:
Say I want to write a wrapper around a simple LED .. It has one method .. "blink" (turns on, sleep(500), turn off) .. very simple logic. As it is now, the .ctor for the class would usually contain the Netduino Pin number to use and internally it would create an OutputPort and the "blink" method would then do its thing. But lets say I wanted to use a 74HC595 .. I should not have to change my fancy led blink class. But I would have to ... because its using the OutputPort internally. What about if I wanted to use a chained 74HC595? Different code for the led class yet again. I also just write a driver for the MCP23017 (16 I/O expander). Would have been yet another special case. Sure, I could use delegates all over the place (e.g, Blink(Action externalAction)) and not have any real logic in my class .. but that is bad design.
However, if I had a standard contract (i.e, IOutputPort), then I could have just passed that interface into the led blink class, and it would just work. I can implement something like this:
public sealed class MCP23017 { public MCP23017(I2CDevice sharedI2C) {} public IOutputPort CreateOutputPort(Pin, initialState) { var outputPort = new MCP23017_OutputPort(this, pin, initialState); outputPort.Initialize(); return outputPort; } private sealed class MCP23017_OutputPort { // private OutputPort that only the MCP23017 can create. } }
and to use something like this:
I2CDevice sharedI2C = new I2CDevice(...); using (var mcp23017 = new MCP23017(sharedI2C)) { // These might look the same, but they are controlled by different devcies. IOutputPort op1 = mcp23017.CreateOutputPort(Pin.GPIO0, false); IOutputPort op2 = new OutputPort(PIn.GPIO0, false); BlinkeyLed led1 = new BlinkeyLed(op1); BlinkeyLed led2 = new BlinkeyLed(op2); while (true) { led1.Blink(); led2.Blink(); } }
So, much cleaner and less code duplication (which means more program space) .. all for the cost of a few interfaces.
Having said all that, I have already started using this approach in all my code (I wrote a wrapper around the standard OutputPort that I am using where necessary).
Roy