# Abstract interfaces as a means of documentation

**URL:** <https://www.ruby-forum.com/t/abstract-interfaces-as-a-means-of-documentation/106941>\
**Category:** Ruby\
**Created:** [June 15, 2007, 3:00pm UTC](https://www.ruby-forum.com/t/abstract-interfaces-as-a-means-of-documentation/106941 "2007-06-15T15:00:54Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![eliben](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/3bc359/32.png) [@eliben](https://www.ruby-forum.com/u/eliben)\
**Post date:** [June 15, 2007, 3:00pm UTC](https://www.ruby-forum.com/t/abstract-interfaces-as-a-means-of-documentation/106941/1 "2007-06-15T15:00:54Z")

</div>

Hi all,

The issue of abstract interfaces has been discussed extensively in  
this group. The general consensus is that Ruby’s duck typing coupled  
with the power of mixins renders solves the vast majority of the  
problems interfaces in general and abstract interfaces in particular  
were designed to solve in static languages like Java and C#.

However, one issue that wasn’t addressed is documentation. An abstract  
interface has the advantage of a single place to actually document the  
interface. Consider a couple Ruby classes that implement the same  
interface:

class FooTypePlayer  
def jump  
…  
end

def climb(arg1, arg2)  
end  
end

class BarTypePlayer  
def jump  
…  
end

def climb(arg1, arg2)  
end  
end

And now I want to document what these methods do (with a block comment  
describing the arguments and return values, presenting examples,  
etc.), and I want the documentation to be reflected in the RDoc of my  
code. What are my options ? As I see it, several:

1. Duplicate the same documentation for each class.

- This is hardly feasible for large class-families and violates DRY.

1. Don’t document. Give the methods and arguments descriptive names,  
and write test cases that show how to use them.

- I will write unit tests anyway, and I definitely try to give methods  
and arguments descriptive names, but a talkative block of  
documentation with examples is essential for anything but trivial  
classes.

1. Create a “dummy” abstract class that doesn’t really do anything  
(and is never instantiated), something like:

# Documentation ! bla bla bla…

class AbstractPlayer

# bla bla bla

def jump; end;

# This method… and returns …, the arguments are …

def climb(arg1, arg2); end;  
end

Now, I can inherit FooTypePlayer and BarTypePlayer from AbstractPlayer  
to show certainly that they’re related, I can also fill in the methods  
of AbstractPlayer by throwing “NotImplementedError”. Although this all  
is unnecessary, it might be a good solution for a single place of  
documenting this interface.

What do you think ?

Eli

---

<div class="post-metadata">

**Author:** ![eliben](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/3bc359/32.png) [@eliben](https://www.ruby-forum.com/u/eliben)\
**Post date:** [June 15, 2007, 8:01pm UTC](https://www.ruby-forum.com/t/abstract-interfaces-as-a-means-of-documentation/106941/2 "2007-06-15T20:01:47Z")

</div>

On Jun 15, 6:57 am, Eli B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:  
[snip]

> 1. Create a “dummy” abstract class that doesn’t really do anything  
> (and is never instantiated), something like:

1. Create a Module and document the method in the module, and then  
include that module in each class. Similar to your abstract class, but  
solves the problems of instantiation, and allows you to mix in methods  
along various axes.

module JumpingClimbingPlayer

# docs here

def jump  
raise “You should implement this per player”  
# or maybe implement the common technique  
end

# same for climb

end

class FooTypePlayer  
include JumpingClimbingPlayer  
def jump  
# specific implementation here  
end  
end

---

<div class="post-metadata">

**Author:** ![eliben](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/3bc359/32.png) [@eliben](https://www.ruby-forum.com/u/eliben)\
**Post date:** [June 15, 2007, 11:21pm UTC](https://www.ruby-forum.com/t/abstract-interfaces-as-a-means-of-documentation/106941/3 "2007-06-15T23:21:14Z")

</div>

> end
> 
> # same for climb
> 
> end
> 
> class FooTypePlayer  
> include JumpingClimbingPlayer  
> def jump  
> # specific implementation here  
> end  
> end

Is this really different from declaring JumpingClimbingPlayer as a  
class and inheriting the concrete classes from it, like:

class FooTypePlayer \< JumpingClimbingPlayer

?

---

<div class="post-metadata">

**Author:** ![eliben](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/3bc359/32.png) [@eliben](https://www.ruby-forum.com/u/eliben)\
**Post date:** [June 16, 2007, 1:53am UTC](https://www.ruby-forum.com/t/abstract-interfaces-as-a-means-of-documentation/106941/4 "2007-06-16T01:53:31Z")

</div>

On 6/15/07, Eli B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Is this really different from declaring JumpingClimbingPlayer as a  
> class and inheriting the concrete classes from it, like:
> 
> class FooTypePlayer \< JumpingClimbingPlayer

Yes. Modules cannot be inherited from or instantiated.

---

<div class="post-metadata">

**Author:** ![eliben](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/3bc359/32.png) [@eliben](https://www.ruby-forum.com/u/eliben)\
**Post date:** [June 16, 2007, 8:10am UTC](https://www.ruby-forum.com/t/abstract-interfaces-as-a-means-of-documentation/106941/5 "2007-06-16T08:10:58Z")

</div>

On Jun 16, 1:53 am, “Gregory B.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On 6/15/07, Eli B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > Is this really different from declaring JumpingClimbingPlayer as a  
> > class and inheriting the concrete classes from it, like:
> 
> > class FooTypePlayer \< JumpingClimbingPlayer
> 
> Yes. Modules cannot be inherited from or instantiated.

Understood, thanks. Another thing - say that for some reason I want my  
classes not to have the default .new constructor, and instead use  
factory methods (for example, it’s important to return values from the  
factory methods, other than the object).

In a normal class, I can say:

class Foo  
private\_class\_method :new

self.create(a, b)  
… # do stuff  
return [new(a, b), message]  
end

private  
def initialize(a, b)  
…  
end  
end

But if I want a class family adhering to an abstract interface (like  
the previous posts show), how can I do that with a Module ? Module  
doesn’t allow the “private\_class\_method” line since it doesn’t have  
a :new method. With an abstract base Class (instead of Module) it _is_  
possible, isn’t it ?

Eli

---

<div class="post-metadata">

**Author:** ![eliben](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/3bc359/32.png) [@eliben](https://www.ruby-forum.com/u/eliben)\
**Post date:** [June 16, 2007, 3:54pm UTC](https://www.ruby-forum.com/t/abstract-interfaces-as-a-means-of-documentation/106941/6 "2007-06-16T15:54:42Z")

</div>

On 6/16/07, Eli B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> But if I want a class family adhering to an abstract interface (like  
> the previous posts show), how can I do that with a Module ? Module  
> doesn’t allow the “private\_class\_method” line since it doesn’t have  
> a :new method. With an abstract base Class (instead of Module) it _is_  
> possible, isn’t it ?

module B

def create  
new(20)  
end

end

class A

extend B

def initialize(foo)  
@foo = foo  
end

def bar  
@foo + 10  
end  
end

c = A.create  
c.bar #=\> 30
