Introducing `Behaves`, a better way to define contracts/behaviors between classes

edisonywh

Edison Yap

Posted on June 7, 2019

Introducing `Behaves`, a better way to define contracts/behaviors between classes

Hey guys!

I just published my first gem on RubyGems, and would love to hear your feedback!

GitHub logo edisonywh / behaves

Define behaviors and contracts between your code.

CircleCI Badge RubyGems Badge Code Climate maintainability

Behaves

Behaves is a gem that helps you define behaviors between classes. Say goodbye to runtime error when defining behaviors.

Behaves is especially useful for dealing with adapter patterns by making sure that all of your adapters define the required behaviors. See usage below for more examples.

Detailed explanations in the sections below.

Installation

Add this line to your application's Gemfile:

gem 'behaves'
Enter fullscreen mode Exit fullscreen mode

Usage

This is how you define behaviors with behaves.

First, define required methods on the Behavior Object with the implements method, which take a list of methods.

class Animal
  extend Behaves

  implements :speak, :eat
end
Enter fullscreen mode Exit fullscreen mode

Then, you can turn any object (the Behaving Object) to behave like the Behavior Object by using the behaves_like method, which takes a Behavior Object.

class Dog
  extend Behaves

  behaves_like Animal
end
Enter fullscreen mode Exit fullscreen mode

Voilà, that's all it takes to define behaviors! Now if Dog does not implement speak and…

Description

Behaves is a gem that helps you maintain contracts between different classes. This is especially useful for dealing for adapter patterns by making sure that all of your adapters define the required behaviors.

The idea for Behaves stemmed from my research into adapter pattern in Ruby and José Valim's article on Mocks and explicit contracts.

I found that the current idiom to achieve behaviors in Ruby is through Inheritence, and then subsequently defining a "required" (I put quotation marks around it, because it's not exactly required until you run it) method, which does nothing except raising a NotImplementedError. While I don't necessarily think it's bad, I do think that there could be an alternative that's more explicit, less boilerplate, cleaner ancestors hierachy, thus the birth of Behaves.

Best of all? No more runtime errors for defining behaviors!

Do let me know what you think!

💖 💪 🙅 🚩
edisonywh
Edison Yap

Posted on June 7, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related