Project

festoon

0.0
No commit activity in last 3 years
No release in over 3 years
Tools for better object composition and decoration
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.7
~> 0.10
~> 10.0
~> 3.0
 Project Readme

Festoon

What is it?

This project aspires to better enable object composition by offering a set of super classes and modules akin to the standard library's SimpleDelegator.

Why is it?

Personally I've felt the delegation tools in the standard library to be lacking in functionality, often difficult to use in practice and sometimes misleading.

The following are issues I have encountered (not comprehensive)

  • Delegation of #inspect causing the SimpleDelegator to masquerade as the object it decorates.
  • Comparison of decorated objects only works for coercible primitives.
  • Fluid interfaces, where the decorated object returns self, are not supported and cause your composed objects to unravel.
  • Difficulty debugging multiple layers of decoration

Examples

Equality

my_object = Object.new

Festoon::Dynamic.new(my_object) == Festoon::Dynamic.new(my_object)
=> true

Fluid interfaces, return of self

class MyClass
  def returns_self
    self
  end
end

my_object = MyClass.new

Festoon::Dynamic.new(my_object).returns_self.class
=> Festoon::Dynamic

Inspection

Festoon::Dynamic.new(my_object).inspect
=> #<Festoon::Dynamic:0x0000010108af28 @thing=#<Object:0x0000010108af50>>

Compose and __decompose__

#__decompose__ returns an array, each element containing a layer of the composed object, outermost first. This is most easily demonstrable by mapping each layer to its class.

This mainly exists for debugging and allow you to inspect, interact with, and bypass arbitrary layers of the composition.

class DecoratorA < Festoon::Dynamic; end

class DecoratorB < Festoon::Dynamic; end

composed_object = DecoratorB.new(DecoratorA.new(MyClass.new))

composed_object.__decompose__.map { |o| o.class }
=> [DecoratorB, DecoratorA, MyClass]

composed_object.__decompose__
=> [
    #<DecoratorB:0x00000102003770 @thing=#<DecoratorA:0x00000102003798 @thing=#<MyClass:0x00000102003e28>>>,
    #<DecoratorA:0x00000102003798 @thing=#<MyClass:0x00000102003e28>>,
    #<MyClass:0x00000102003e28>
  ]

TODO

  • Method reflection methods such as #public_methods etc
  • Consider delegation of #trust, #untrust, #taint, #untaint, #freeze
  • #inspect method which has readable output and does not attempt to hide the object's composed nature. Potentially offer a set of strategies for this
  • Recursive #dup?
  • Hash equality
  • Rename @thing

Installation

Add this line to your application's Gemfile:

gem "festoon"

And then execute:

$ bundle

Or install it yourself as:

$ gem install festoon

Usage

TODO: Write usage instructions here

Contributing

  1. Fork it ( https://github.com/[my-github-username]/festoon/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request