G
Gavin Kistner
--Apple-Mail-2--468029632
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
format=flowed
Summary
I'm looking for advice on how to design code so that I can dynamically
add/remove instantiable classes, where each of these classes have
values for a set of properties defined by a parent class.
Details
I'm starting to design/write an uber-ambitious home automation hub, in
Ruby. In addition to having convenient things like a web-based GUI
front-end, scheduler, and so on, the heart of this application is that
it will (eventually) work with any automation hardware whose
communication protocol is open (or reverse-engineered).
The plan is to have 'adaptors' for each discrete hardware type, which
encapsulate all the guts of the communication protocol and expose
methods for that bit of hardware. The user can then 'instantiate' one
or more of these adaptors, representing physical instances of that bit
of hardware in the home.
(For example, there's a single "Lutron RadioRA Wall Dimmer" adaptor,
but the user may have 4 such switches in the house, named "Front
Kitchen Lights", "Rear Kitchen Lights", "Bedroom Lights", and "Entry
Lights".)
In addition to custom methods, each adaptor needs to expose some common
information, such as its name, manufacturer, category, sub-category,
model number, and so on.
I initially decided to have code like this:
me = Foo::Bar:eviceType.new( 'Lutron RadioRA Wall Dimmer', :Lutron,
:Switches, immers, 'RA-ND6' )
me.add_action( :turn_on, Proc.new{ ... } )
me.add_action( :turn_off, Proc.new{ ... } )
me.add_action( :level=, Proc.new{ ... } )
me.add_action( :level, Proc.new{ ... } )
#...and then later do something like...
Foo::Bar::add_device( 'Entry Lights', blah )
# ...where blah is a pointer to the DeviceType instance
But then I realized that I'm mostly just putting a wrapper around a
class definition. Further, I realized that I want all adaptors to
support common methods (name, manufacturer, model number), all light
switches to support some common methods (turn_on, turn_off), and all
dimmers to support others still (level= and level). This reeks of a
class hierarchy, so I was thinking that I might do something like:
# Core app
class Foo::Bar:eviceType
def name; raise "Implement Me!"; end
def manufacturer; raise "Implement Me!"; end
def model; raise "Implement Me!"; end
class Light
def turn_on; raise "Implement Me!"; end
def turn_off; raise "Implement Me!"; end
class Dimmer
def level=(n); raise "Implement Me!"; end
def level; raise "Implement Me!"; end
end
end
end
#Adaptor file
class Foo::Bar:eviceType::Light:immer::RadioRA
def name; 'Lutron RadioRA Wall Dimmer'; end
def manufacturer; 'Lutron'; end
def name; 'RA-ND6'; end
def turn_on; ...; end;
def turn_off; ...; end;
def level=(n); ...; end;
def level; ...; end;
Foo::Bar:eviceType::add_device( self )
end
... and the add_device method would
a) Create a dummy parent class and run through all the methods to see
if they throw errors.
b) Add the class into a list of instantiable adaptors if it works.
Questions
1) Is there a way to inspect the runtime state and figure out which
subclasses exist for a given class?
2) Is there a better way to force/detect if a subclass implements
certain methods?
3) Is there a better way overall to achieve my goal?
Thanks if you even read this far. Thanks even more if you take the time
to think about the problem and offer suggestions.
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
format=flowed
Summary
I'm looking for advice on how to design code so that I can dynamically
add/remove instantiable classes, where each of these classes have
values for a set of properties defined by a parent class.
Details
I'm starting to design/write an uber-ambitious home automation hub, in
Ruby. In addition to having convenient things like a web-based GUI
front-end, scheduler, and so on, the heart of this application is that
it will (eventually) work with any automation hardware whose
communication protocol is open (or reverse-engineered).
The plan is to have 'adaptors' for each discrete hardware type, which
encapsulate all the guts of the communication protocol and expose
methods for that bit of hardware. The user can then 'instantiate' one
or more of these adaptors, representing physical instances of that bit
of hardware in the home.
(For example, there's a single "Lutron RadioRA Wall Dimmer" adaptor,
but the user may have 4 such switches in the house, named "Front
Kitchen Lights", "Rear Kitchen Lights", "Bedroom Lights", and "Entry
Lights".)
In addition to custom methods, each adaptor needs to expose some common
information, such as its name, manufacturer, category, sub-category,
model number, and so on.
I initially decided to have code like this:
me = Foo::Bar:eviceType.new( 'Lutron RadioRA Wall Dimmer', :Lutron,
:Switches, immers, 'RA-ND6' )
me.add_action( :turn_on, Proc.new{ ... } )
me.add_action( :turn_off, Proc.new{ ... } )
me.add_action( :level=, Proc.new{ ... } )
me.add_action( :level, Proc.new{ ... } )
#...and then later do something like...
Foo::Bar::add_device( 'Entry Lights', blah )
# ...where blah is a pointer to the DeviceType instance
But then I realized that I'm mostly just putting a wrapper around a
class definition. Further, I realized that I want all adaptors to
support common methods (name, manufacturer, model number), all light
switches to support some common methods (turn_on, turn_off), and all
dimmers to support others still (level= and level). This reeks of a
class hierarchy, so I was thinking that I might do something like:
# Core app
class Foo::Bar:eviceType
def name; raise "Implement Me!"; end
def manufacturer; raise "Implement Me!"; end
def model; raise "Implement Me!"; end
class Light
def turn_on; raise "Implement Me!"; end
def turn_off; raise "Implement Me!"; end
class Dimmer
def level=(n); raise "Implement Me!"; end
def level; raise "Implement Me!"; end
end
end
end
#Adaptor file
class Foo::Bar:eviceType::Light:immer::RadioRA
def name; 'Lutron RadioRA Wall Dimmer'; end
def manufacturer; 'Lutron'; end
def name; 'RA-ND6'; end
def turn_on; ...; end;
def turn_off; ...; end;
def level=(n); ...; end;
def level; ...; end;
Foo::Bar:eviceType::add_device( self )
end
... and the add_device method would
a) Create a dummy parent class and run through all the methods to see
if they throw errors.
b) Add the class into a list of instantiable adaptors if it works.
Questions
1) Is there a way to inspect the runtime state and figure out which
subclasses exist for a given class?
2) Is there a better way to force/detect if a subclass implements
certain methods?
3) Is there a better way overall to achieve my goal?
Thanks if you even read this far. Thanks even more if you take the time
to think about the problem and offer suggestions.