That's the idea, and with a small project, it seems the way to go-
just have any class that wants to be a protocol implement login,
logout, send, receive.
Similarly, you may might want your protocol classes to implement IO
methods, such that it can seamlessly take place of an IO object or
File object.
If, you find problems with run-time errors due to a large number of
erronous new protocols being implemented that escape unit-tests, you
could define a protocol not so much as a type, but as a contract.
module Protocol
attr :login, :logout, :send, :receive # alternative- implement
methods with a "raise Exception" in the body, forcing overrides in the
class mixinng in Protocol. But a more general method, like shown below
in MyProtocol, is cleaner and saves typing in the long run.
end
class MyProtocol
protocol Protocol # where protocol is a custom include like
method that does a design-by-contract type check that all of
Protocol's methods are implemented.
end
MyProtocol will now thow an exception until it implements all 4
methods. And it explicitly documented my contract for the programmer
looking at the code.
But I'm leaning away from even this lately. Last month I still liked
interfaces a-la Java, and that's largely disipated. Maybe next month
I'll have quacked-up completely, and not worry about protocols either.
I'm still waiting to see how my code talks to me as I write larger
Ruby programs.
Considering protocols some more, I find that in Ruby itself, I find
myself thinking in terms of interfaces/protocols as implicitly defined
by core ruby, example- e.g. Enumerable, Comparable, Array, Hash, IO,
BasicSocket as a few. While these don't enforce any implementation
contract to go with their interface example, they provide a set of
implied interfaces for my mind to consider.
This set turns out to be quite broad, and I don't find many impluses
to create others, such as your Protocol class. It usually seems to
have little value. But I can still perceive the need in a larger
system that has a lot of variations on a unique object type (e.g.
Document in a large document management system). But then, a module
usually emerges for reasons of factoring out common functionality, and
it handles the explicit protocol definition quite well as a side
effect, rather then a explicit goal. So the module, while not
providing enforced implementation of a protocol, does provide good
documentation of what it is, and a mental concept to think with. And
if a module doesn't appear to satisfy other needs, such as common
functionality, then your probably don't have enough complexity to
really benefit from an explicitly defined interface anyhow.
Now if you ship a framework, or have lots of programmers working on
the project, then adding the ability to ensure implementation of
certain methods through an explict protocol mechanism like the one
considered above becomes interesting. But some would argue the unit
tests would provide the implementation contract. But I'm not sure of
that- the person subclassing may not write test, or even if they do,
they may not understand the full ramifications of the class they are
extending. And, the original unit tests might not automatically pick
up sub classes.
Note that while the protocol-pattern is somewhat like a Java interface
(which is like an ObjectiveC protocol...), general Ruby programming
patterns would never make use of it anyway. Usually it's typed
variables, typed collections (e.g. generics or custom collections), or
casts that make use of interfaces or parent classes. And if you start
adding code to get a similar effect, you are way-gone from
duck-typing.
Now that I've written this, it occurs to me that maybe I'm really
thinking about design-by-contract (DBC), with one case being ensuring
the implementation of a certain protocol/set of methods. But since the
concept of protocol isn't used for anything else, maybe it's better
consider as a DBC need being applied uniquely in cases where
unit-testing doesn't suffice.
Okay, so I've now punted on interfaces and protocols, and am left
brooding over DBC. I wonder if there have been any interesting
discussions on the value of DBC in Ruby. Something to google for later
this week.
Regards,
Nick
···
--
Nicholas Van Weerdenburg
On Tue, 25 Jan 2005 07:42:13 +0900, Edgardo Hames <ehames@gmail.com> wrote:
Hi, you all.
I'm working on a new small project where several network protocols are
to be supported. I had an idea about how to implement it and it
resembled something like this.
class Protocol
abstract :login, :logout, :send, :receive
end
class MyProtocol < Protocol
def login
# does something useful
end
... # so on
end
Then my network client would just call the methods of a Protocol
object without caring about the actual classes that implement it (yes,
you're right, I come from a static typing background). But then I read
something (I don't remember where ) which said that agile languages
don't need to implement so many patterns and I think I saw the light!
I don't need a Protocol class, the network client should just call the
methods of the protocol and duck typing should do all the magic. Am I
right? Am I coming a little closer to walking the Ruby Way?
Please, post a positive reply and you just may save me a couple of
therapy sessions
Kind Regards,
Ed
--
Alcohol is the anesthesia by which we endure the operation of life.
-- George Bernard Shaw