¿Es aplicable la 'Ley de Demeter' a las firmas de métodos públicos / API?

10

Dado que los cambios en la firma de API / método público deberían ser mínimos para evitar romper los códigos de clientes que usan estos métodos, me preguntaba si la Ley de Demeter es menos aplicable a estos.

Un simple ejemplo:

class Account() {
   double balance;
   public void debit(Transaction t) {
      balance -= t.getAmount();
   }
}

Tenga en cuenta que el método de débito pasa el objeto Transacción en lugar de solo la cantidad doble (la 'Ley de Demeter', según tengo entendido, diría que solo pase la información requerida, en este caso solo la cantidad, no el objeto Transacción ... ) La razón detrás de esto es porque el método en el futuro podría requerir algunas otras propiedades de Transacción aparte del monto. Por lo que entiendo, esto evitará romper la firma del método al agregar un nuevo parámetro en el futuro.

¿Esto lo convierte en una opción sensata entonces? ¿O me estoy perdiendo algo?

Carlos Jaime C. De Leon
fuente

Respuestas:

3

Pero esto no infringe la Ley de Deméter.

Más formalmente, la Ley de Demeter para funciones requiere que un método M de un objeto O solo pueda invocar los métodos de los siguientes tipos de objetos:

  • O mismo
  • Parámetros de M
  • cualquier objeto creado / instanciado dentro de M
  • Objetos componentes directos de O
  • Una variable global, accesible por O, en el ámbito de M

Wikipedia: Ley de Demeter

La transacción es un argumento para el método de débito, por lo que llamar a t.getAmount () está bien.

Editar: leyó mal, está diciendo que el LoD le haría pasar el monto de la transacción, no un objeto Transacción. Si ese es el caso, entonces sí, creo que este es un buen lugar para romperlo, sabiendo que necesitará más del objeto Transacción en el futuro. Además, encapsular primitivas en objetos de nivel de dominio es otra buena práctica de programación.

Edición 2: Habiendo leído que podría necesitar más en el futuro, uno también podría ver esto como un chapado en oro innecesario. Proporcionar un método que tome un doble ahora (o mejor una clase de dinero) es suficiente. Si necesita un argumento de Transacción más tarde, no es desastroso proporcionar una segunda firma que tome una Transacción, pero continúe admitiendo la firma original. No es como si implementaras dos métodos, uno llamaría al otro.

Sean
fuente
Gracias por tu contribución. Estoy de acuerdo con las primitivas de encapsulación en objetos de dominio. Sin embargo, solo su punto en Edit 2, dice que no es desastroso agregar una segunda segunda firma, pero eso significaría un cambio de código en el código del cliente que ahora debería pasar 2 parámetros en lugar de uno. Ese segundo punto, dudo mucho en acordar ...
Carlos Jaime C. De Leon
Edit 2 es subjetivo, estoy de acuerdo.
Sean
0

Si planeas expandir la Accountclase en el futuro, diría que esta es una situación en la que hacer que el Transactionobjeto tenga un propósito más general sería una buena flexión de las reglas de la Ley.

Por ejemplo:

public class Amount {

    public void process( Transaction t ) {
        ....
    }
}

public abstract class Transaction {

    public String getType();

}

Creo que me estoy desviando de la pregunta original, pero mi punto es que, si bien te puede preocupar que te estés desviando de la Ley de Deméter, las ventajas de hacerlo superan a los negativos.

chooban
fuente