title | parent |
---|---|
Single Responsibility Principle |
SOLID |
{: .fs-3 }
Especially when applying Stimulus to your application for the first time, it is tempting to write your controllers in a page controller style, resulting in a disjointed accumulation of unrelated functionality. Resist that temptation - try to write reusable controllers.
Below is a shortened juxtaposition of what that could look like.
Bad {: .label .label-red }
<!-- page.html -->
<div data-controller="page">
<form action="/" data-target="page.form"></form>
<div data-target="page.modal" class="modal"></div>
</div>
{: .border-red}
// page_controller.js
import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["modal", "form"];
openModal() {
this.modalTarget.classList.add("open");
}
submitForm() {
this.formTarget.submit();
}
}
{: .border-red}
Good {: .label .label-green }
<!-- page.html -->
<div>
<form action="/" data-controller="form"></form>
<div data-controller="modal" class="modal"></div>
</div>
{: .border-green}
// modal_controller.js
import { Controller } from "stimulus";
export default class extends Controller {
open() {
this.element.classList.add("open");
}
}
{: .border-green}
// form_controller.js
import { Controller } from "stimulus";
export default class extends Controller {
submit() {
this.element.submit();
}
}
{: .border-green}
Books have been written about this very single topic, but let it be said that classes/modules that serve a single responsibility are
- easy to reuse - in our example above the
page_controller
can only be used on this very page (or one with the same structure), whereasmodal_controller
andform_controller
could be used on any modal or form element, and - easy to change - because every responsibility has a single point of realization, changes are cheap: instead of having to implement a new functionality in several places, there's only one spot where you have to install the new behavior.
- Practical Object Oriented Design by Sandi Metz
- Wikipedia