[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

"Duck Typing" or "No need for abstract classes"

Edgardo Hames

1/24/2005 10:42:00 PM

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 :P

Kind Regards,
Ed

--
Alcohol is the anesthesia by which we endure the operation of life.
-- George Bernard Shaw


46 Answers

Jamis Buck

1/24/2005 10:58:00 PM

0

On 07:42 Tue 25 Jan , Edgardo Hames 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?

You've got it! Congratulations. :)

>
> Please, post a positive reply and you just may save me a couple of
> therapy sessions :P

I'm happy to be of service. That'll be $250. :-P

>
> Kind Regards,
> Ed
>
> --
> Alcohol is the anesthesia by which we endure the operation of life.
> -- George Bernard Shaw
>
>

--
Jamis Buck
jamis_buck@byu.edu
http://jamis.jam...
------------------------------
"I am Victor of Borge. You will be assimil-nine-ed."



Nicholas Van Weerdenburg

1/24/2005 11:40:00 PM

0

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 :P
>
> Kind Regards,
> Ed
>
> --
> Alcohol is the anesthesia by which we endure the operation of life.
> -- George Bernard Shaw
>
>


Mathieu Bouchard

1/25/2005 6:58:00 AM

0

Robert Klemme

1/25/2005 8:18:00 AM

0


"Edgardo Hames" <ehames@gmail.com> schrieb im Newsbeitrag
news:478c16ae0501241442501dc6e5@mail.gmail.com...
> 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 :P

:-) You're compltely right.

Some additional musings: In your case I'd add a base class only if all
protocols share some common behavior or state. This keeps redundancy low.

# example
class Protocol
def cycle
session = login

begin
yield session
ensure
logout
end
end

def send_all(*a)
a.each {|x| send x}
end
end

Another reason might be that you have to plan for future extensions and
you want to have a place to put them. Then you can justify an empty base
class because if you have lot's of protocols it might be tedious to add
the base class later.

Kind regards

robert

Curt Sampson

1/25/2005 10:37:00 AM

0

Lothar Scholz

1/25/2005 11:55:00 AM

0

Hello Curt,

CS> On Tue, 25 Jan 2005, Mathieu Bouchard wrote:

CS> Of course, creating something like this is much harder in a language
CS> like Ruby where objects are ever-changing and ever-malliable. But even
CS> for Ruby it should be possible to do it at least to some extent, falling
CS> back to exceptions at runtime if you're doing something tricky (such as
CS> adding and removing singleton methods on an object on the fly).

100% ACK.
As a toolwriter i often get requests: I want a good working
refactoring browsers, where are the code tooltips,
can't you integrate a ruby lint etc.

These tools all need a type inference engine and this is a huge task.
If someone wants to start with it perfect. I really want to see the
heuristics that are used. And i really hope that ruby gets some common
agreements how to write type assertions very soon.

I recently read an article on www.smalltalk.org about the python
typing extension. It's bad to see that so many people don't understand
that this technique can be optional and some hints are much better then none. We
don't need to be able to specify everything, but in most cases it's
very easy and very helpful to do so.


--
Best regards, emailto: scholz at scriptolutions dot com
Lothar Scholz http://www.ru...
CTO Scriptolutions Ruby, PHP, Python IDE 's




Pit Capitain

1/25/2005 2:48:00 PM

0

Lothar Scholz schrieb:
> CS> On Tue, 25 Jan 2005, Mathieu Bouchard wrote:
> CS> Of course, creating something like this is much harder in a language
> CS> like Ruby where objects are ever-changing and ever-malliable
...
> 100% ACK.
> As a toolwriter i often get requests: I want a good working
> refactoring browsers, where are the code tooltips,
> can't you integrate a ruby lint etc.
>
> These tools all need a type inference engine and this is a huge task.
...

I'm sure you know where the original refactoring browser came from. Your last
statement is simply wrong.

Regards,
Pit


Its Me

1/25/2005 3:07:00 PM

0


"Pit Capitain" <pit@capitain.de> wrote
> Lothar Scholz schrieb:
> > CS> On Tue, 25 Jan 2005, Mathieu Bouchard wrote:
> > CS> Of course, creating something like this is much harder in a language
> > CS> like Ruby where objects are ever-changing and ever-malliable
> ..
> > 100% ACK.
> > As a toolwriter i often get requests: I want a good working
> > refactoring browsers, where are the code tooltips,
> > can't you integrate a ruby lint etc.
> >
> > These tools all need a type inference engine and this is a huge task.
> ..
>
> I'm sure you know where the original refactoring browser came from. Your
last
> statement is simply wrong.

Smalltalk's refactoring browser is image-based. The environment is working
on the end-result of all dynamic stuff (with the effective source
representation of that end-result). If you have dynamically added a method
to a class, that method shows up in the browser (I think!).

Wouldn't it be far more difficult to implement such a tool based solely on
the source-code that caused all that dynamic stuff to happen in the first
place.

Is image-based tooling a mismatch for Ruby? Hmmm.


Lothar Scholz

1/25/2005 3:18:00 PM

0

Hello Pit,

PC> Lothar Scholz schrieb:
>> CS> On Tue, 25 Jan 2005, Mathieu Bouchard wrote:
>> CS> Of course, creating something like this is much harder in a language
>> CS> like Ruby where objects are ever-changing and ever-malliable
PC> ...
>> 100% ACK.
>> As a toolwriter i often get requests: I want a good working
>> refactoring browsers, where are the code tooltips,
>> can't you integrate a ruby lint etc.
>>
>> These tools all need a type inference engine and this is a huge task.
PC> ...

PC> I'm sure you know where the original refactoring browser came from. Your last
PC> statement is simply wrong.

If i remember correctly the first version was not more intelligent
then a grep with some good regexprs (for the most important "rename
method" and "rename class" refactoring moves) all later versions have
a build in type inference engine based on heuristics.

This can be done much much easier in smalltalk so the type inference
does not need so much explicit written help.

Remember that even things like counting argumetns in a method
invocation and comparing that with the arguments in a def statement to
find out if this is a possible invocation of the declaration is a very
simple type inference engine.


--
Best regards, emailto: scholz at scriptolutions dot com
Lothar Scholz http://www.ru...
CTO Scriptolutions Ruby, PHP, Python IDE 's




Nicholas Van Weerdenburg

1/25/2005 3:35:00 PM

0

On Wed, 26 Jan 2005 00:10:49 +0900, itsme213 <itsme213@hotmail.com> wrote:
>
> "Pit Capitain" <pit@capitain.de> wrote
> > Lothar Scholz schrieb:
> > > CS> On Tue, 25 Jan 2005, Mathieu Bouchard wrote:
> > > CS> Of course, creating something like this is much harder in a language
> > > CS> like Ruby where objects are ever-changing and ever-malliable
> > ..
> > > 100% ACK.
> > > As a toolwriter i often get requests: I want a good working
> > > refactoring browsers, where are the code tooltips,
> > > can't you integrate a ruby lint etc.
> > >
> > > These tools all need a type inference engine and this is a huge task.
> > ..
> >
> > I'm sure you know where the original refactoring browser came from. Your
> last
> > statement is simply wrong.
>
> Smalltalk's refactoring browser is image-based. The environment is working
> on the end-result of all dynamic stuff (with the effective source
> representation of that end-result). If you have dynamically added a method
> to a class, that method shows up in the browser (I think!).
>
> Wouldn't it be far more difficult to implement such a tool based solely on
> the source-code that caused all that dynamic stuff to happen in the first
> place.
>
> Is image-based tooling a mismatch for Ruby? Hmmm.
>
>

This is the impression I've gotten- that a live image system uses the
objects that exist while programming against a live system to do code
completion, etc. In effect, this is what irb completion does.

As for the inference engine, I'd be very happy with a 80% accurate
solution- e.g. the really dumb cases. It would offer a great
performance boost, IMHO.

I have to admit though- the level of trust I have with the IntelliJ
IDEA refactoring tools is so high, I never think twice about
refactoring. However, with unit tests and version control in the ruby
world, I would be pretty comfortable as well. All I need is a good
impact report with a "Do it!" button.

Interestingly, Rails seems to be evolving into a pseudo-image-like
system, with class reloads and breakpoints that spawn irb sessions.
Conceivably an editor could be smart enough to bind to the running
environment.

Regards,
Nick
--
Nicholas Van Weerdenburg