Skip to content

Instantly share code, notes, and snippets.

@malakai97
Last active March 22, 2024 20:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save malakai97/6ecbc52b46319b33eb574d089fcd7c87 to your computer and use it in GitHub Desktop.
Save malakai97/6ecbc52b46319b33eb574d089fcd7c87 to your computer and use it in GitHub Desktop.
Modules in Ruby

Modules in Ruby

On Composition

There has been sentiment that ruby's modules enable composition, but this is not the case. Composition describes a "has-a" relationship, whereas (in ruby) when a class includes a module, it creates an is-a relationship.

Forms/Patterns

There are four basic forms of modules in ruby, some good, some not so good.

Value Types

Modules that define access to a value type on the class. Other than providing the convenience of using the value type, the module doens't do anything else. Typically, they add DSL methods. It does not modify the interface of the class beyond receiving objects of the value type or returning them. This usage is generally considered safe.

Ex. Cash, Vector

Subscription

Modules that depend on the class. These apply a set of functionality to the object that the class otherwise does not know about. This is akin to the module concern subscribing (or acting as a subscription) to the class. This sort of usage is easy to mess up. The litmus test is you should be able to remove the module from the class, without compromising the class's ability to carry out its responsibility. Likewise, you could make changes to the module without having to make changes to the class.

The most common example is monitoring entities for changes.

Interfaces and Pseudo-Inheritance

Modules that functionally act as a superclass (when the module has method implementations) and modules that act as an interface (when the module's methods are unimplemented). We group these together because it's a spectrum. These types of modules can usually be cleanly replaced with superclasses and traditional inheritance. That makes the relationship clear: the class depends on the module, but the module does not know about the class.

This usage is moderately more dangerous than traditional inheritance.

Intermingled

Modules that both depend on and are depended upon by the class. This relationship is a bidirectional dependency; it comes with tight coupling with every class that includes it, and transitively introduces coupling between those classes. Further, usage of modules in this fashion tends to compound as intermingled modules are intermingled with other modules.

Module usage in this way should be avoided whenever possible, and those remaining use cases should be eyed with scrutiny and suspicion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment