Design Advice: Sub-Class 'Instances'

Y

Yukihiro Matsumoto

Hi,

It's too late for me (4:45am) now. Short answer:

In message "Re: [BUG] 1.8.1 & 2 proc bug"

| * Is it too late to argue against this change?

No. It's a hot topic having experiment on CVS HEAD. You can discuss both

* how should it behave in Ruby2.
* how should it behave in 1.8.2.

But since 1.8.2 is becoming close, you don't have much time for 1.8
behavior.

matz.
 
M

Markus

Matz --

Sleep well. I will try to have something cogent on both points
posted to this list before you wake.

-- Markus
 
G

Gavin Kistner

If I understand rightly, I think the main constraint here is that you
want
to organise the classes logically for the user to see when selecting
one (to
create a new instance of a DimmerSwitch, for example, selecting it
from a
tree rather than a long linear scrolling list).

I'd say it's one of two main constraints, and I'd expand upon it a
little:

1) I want to organize the classes logically into a thought-out
hierarchy, ensuring that similar classes are correctly presented to the
user.

2) I want to ensure that the methods exposed by similar classes are
presented to the user in a very consistent manner.

In both cases, my philosophy says that I shouldn't trust authors to to
the Right thing, despite any clear guidelines I might provide. They
either won't read them, or where it's a matter of taste ("What's the
best place for this in a hierarchy?") they'll differ from my Grand
Plan.

My philosophy says that I should make it hard for them to screw up, not
hard for them to succeed. It's hard for many people to come up with
something elegant, given a blank canvas. My goal is to define the
equivalent of a layout template for a magazine page, making it easier
for them to create the end product. "Just plug stuff in here, here, and
here, and choose one of the existing hierarchy categories, and you're
done!"

Now, the implementation of these goals is not necessarily best served
through the class hierarchy. For example, you're dead right-on that the
namespace issue should be organized by author/manufacturer. I don't
know what I was thinking, trying to place it under the
hierarchy-of-devices namespace. (Well, I do know: I was yet-again
confusing thoughts of namespace hierarchy with inheritance hierarchy.)

module GavinKistner
def author; "Gavin Kistner; end
def author_url; "http://phrogz.net/"; end
module Lutron
def manufacturer; "Lutron"; end
def manufacturer_url; "http://www.lutron.com/"; end
class OnOffDimmer < Foo::Bar::Electrical::Switches::Dimmer
include GavinKistner
include Lutron
def name; "Lutron RadioRA Dimmer"; end
#...
register_adaptor
end
end
end

That's what I'm leaning towards now, and it's so much cleaner than
Foo::Bar::Electrical::Switches::Dimmer::LutronRadioRADimmer <
Foo::Bar::Electrical::Switches::Dimmer

Authors *will* be able to screw up my application, due to the
gloriously dynamic nature of Ruby. It would be trivial for a stubborn
author to add their own bizarre path to the classification hierarchy.
(And should be allowed, as well; I am not so egotistical to imagine
that my initial hierarchy will be perfect.) But I'd prefer to provide
them with an existing hierarchy to drop their class into, and provide
guidelines for the basic functionality they should provide.

[Hrm, aside: given the need to allow authors to run arbitrary code to
communicate to/from the device, is there any hope of preventing the
malicious author from supplying a trojan-horse module which does
nefarious things alongside a bit of benefit?]
You can always have a separate hierarchy for display purposes - or even
multiple different hierarchies, or the same class popping up in
multiple
places in the same displayed hierarchy. It doesn't have to follow a
class or
module hierarchy, and although it could, I think it will limit your
flexibility if you do.

You might, for example, want to give one view organised by
manufacturer, and
another organised by device type.

Using a single class hierarchy to classify devices will make it hard to
place the objects in more than one classification hierarchy, and hard
to place the same object in more than one spot in the hierarchy. I
think I need to ponder fully whether or not either of these are
problems, however. At the moment, I don't think they are, but I haven't
really tried to categorize every sort of automation device that I can
think of.

However, it doesn't prevent me from creating alternate views which sort
by manufacturer, author, etc. ... provided that each adaptor class
exposes this information. (Yet another reason that I need to ensure
that certain methods are present on every class.)

require 'homecontrol'
module ACMEwidgets
class OnOffSwitch
def self.indexcard
[Homecontrol::DevType::Switch, "ACME Widgets model 345X mains
controller"]
end
end
end

Although I think there's far too much information (and too dynamic) to
handle in a single 'card', this makes me think of an interesting idea,
allowing multiple classification hierarchies, and placement within more
than one spot in the same hierarchy:

module ACMEwidgets
class OnOffSwitch < Foo::Bar::Device
stick_in( ByType::Electrical::Switch,
ByType::Switches::Special,
ByUse::Lighting::Switch )
end
end

class Foo::Bar::Device
def self.stick_in( *classes )
classes.flatten.each{ |k|
k.add_device( self )
}
end
end

Basically, creating namespace hierarchies which aren't used for
inheritance, but simply for their hierarchical classification
potential.

Although really, I think that end users are not likely to be invoking
methods on their devices directly (unless they are Hal), in which case
the
GUI can take care of it.

You are correct; the GUI will invoke all methods directly. However, I
can't have:

module Author1
class OnOffSwitch
def turn_on; ...; end
def turn_off; ...; end
end
end

module Author2
class DimmerSwitch
def get_jiggy; ...; end
def sleepy_time; ...; end
end
end


I "can't" have that because I'm planning on displaying exposed methods
to the user via

pretty_names = DimmerSwitch.instance_methods.map{ |meth_name|
meth_name.gsub(/_/,' ').gsub(/\b\w/){ |c| c.upcase }
}


Hence my desire to specify certain methods which they must supply
(methods which are reasonable for that class of device). In doing so, I
both ensure that the adaptor has a bare-minimum of functionality, and
that its functionality is consistent with similar adaptors.
What exactly are you
going to do if the class turns out not to have a method that you claim
is
mandatory? I guess you could write code which automatically mails the
offending module back to the author and rm's it from the filesystem!
:)

No, but in addition to throwing a warning to stdout, I very well may
choose not to expose the adaptor in the GUI. "Finish the bare minimum
of functionality if you want your code to be useful."


Thanks for the good advice, and continuing to make me think through
details.
(Planning? What's that?)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top