Putting it together

by Luismi Cavallé

Aunque Demeter ya ha sido mencionado aquí, revisitar estas cosas de vez en cuando siempre viene bien. Lo que nos dice la ley de Demeter es que desde un método debemos evitar invocar métodos que no sean del mismo objeto o de sus “amigos” inmediatos. Así, un ejemplo de violación de esta regla sería un código como este:

@course.school.owner.country.currency_code

La razón por la que este código es problemático es que, al invocarlo, estamos suponiendo la existencia de un árbol de objetos concreto. Estamos suponiendo que un curso tiene una escuela, que la escuela tiene un propietario, que este pertence a un país, y que, finalmente, el país tendrá asociada una moneda. Cualquier cambio en esta premisa supondrá que esto deje de funcionar. A este fenómeno se le llama acoplamiento, y si no se controla adecuadamente puede dar lugar a un código menos mantenible de lo deseable. En este tipo de situaciones, introducir un pequeño cambio en una clase suele suponer tener que hacer pequeños retoques en un montón de clases, muchas de las cuales tendrán poco o nada que ver con el cambio introducido.

Cualquier cadena de llamadas como la del ejemplo debe advertirnos de un posible problema con Demeter. Otra mal olor al respecto, si se testea usando mocks, es que se tengan que definir muchas expectativas en cadena.

Para evitar este problema, en Rails podemos usar el método delegate, que nos lo pone muy fácil. Nuestro modelo quedaría más o menos así:

class Course
  belongs_to :school
  delegate :currency_code, :to => :school
  ...

class School
  belongs_to :owner, :class => User
  delegate :currency_code, :to => :owner
  ...

class User
  belongs_to :country
  delegate :currency_code, :to => :country
  ...

Con esto podríamos cambiar nuestro código original por este…

@course.currency_code

…y con ello minimizar el impacto de futuros cambios en cualquier parte del modelo.