Tell Don’t ask es un principio de la programación orientada a objetos ( POO) que nos recuerda que no tenemos que usar los objetos para pedirles cosas o datos primero y según la información que nos devuelven tomar decisiones
Por el contrario, el principio nos sugiere es decirles a los objetos que hagan cosas y estos objetos internamente tomaran sus propias decisiones según de su estado actual.
Este principio encaja perfectamente con la idea de que un objeto se define por su comportamiento; y además es fundamental para sacar provecho al polimorfismo y la inversión de control.
Es decir si nos dedicamos a preguntar y tomar nosotros las decisiones estaremos acoplándonos, será prácticamente imposible hacer cambios al objeto en un futuro.
Estaríamos también incumpliendo el “principio Open/Close” de los “principios de SOLID”, nuestro sistema será más difícil de mantener, y por lo tanto poco escalable.
Al ser expuesto el estado de una clase a las demás para que pueda ser manipulada estamos violando su encapsulamiento y por ende moviendo las responsabilidades a las clases de mayor nivel.
¿Usas GETTERS y SETTERS en tus Clases?
Si tu respuesta es sí lo mas probable es que estés inclumpliendo el principio “ Tell Don’t Ask “. Ya que por lo general tendemos a usar estos métodos de nuestras clases para asignar y devolver datos.
Por lo que entonces, desde las clases desde donde instanciemos los objetos, seguramente estaremos haciendo uso de un getter para comprobar su estado o valor, y dependiendo del esto, hacer uso del setter para modificar su estado.
Estaríamos también delegando al controlador aplicar reglas y validaciones que quizás sean de negocio y por ende deban encapsularse en nuestros objetos de clase.
Para solucionar esto, lo mejor sería utilizar métodos semánticos y aplicar el principio de “ Tell Don´t Ask “ para delegar la responsabilidad de validaciones y comprobaciones al objeto como tal, manteniendo entonces nuestros objetos encapsulados.
Ejemplo de violación del principio Tell Don´t Ask
class InvoiceController
{
public function payAction()
{
// ...
$userBalance = $user->getBalance();
if ($userBalance < $invoiceTotal) {
throw new NotEnoughFundsException();
}
$newBalance = $userBalance - $invoiceTotal;
$user->setBalance($newBalance);
// ...
}
}
Podemos ver en el ejemplo anterior, usamos un getter ($user->getBalance()
) para obtener un valor, y luego en base a ese valor, del lado del controlador, realizamos comprobaciones. Aquí estamos violando el principio.
Ejemplo correcto del principio Tell Don´t Ask
class InvoiceController
{
public function payAction()
{
// ...
try {
$user->payInvoice($invoice);
} catch (NotEnoughFundsException $e) {
// ...
}
// ...
}
}
Y en el objeto user, dentro del método “**payInvoice(...)
**" realizar las comprobaciones pertinentes, y si todo va bien, procedemos a realizar el action requerido, de lo contrario, arrojar una excepción la cual debe ser controlada en el lado del controlador.
Y de esta forma podemos entonces aplicar este principio en nuestros desarrollo para cumplir con una arquitectura de código limpia y acoplándonos a los principios de la POO.
Recuerda que si tienes alguna sugerencia o pregunta, no dudes en dejar tus comentarios al final del post.
Si te gustó este post, ayúdame a que pueda servirle a muchas más personas, compartiendo mis contenidos en tus redes sociales.
Espero que este post haya sido de gran ayuda para ti, y como siempre, cualquier inquietud o duda que tengas, puedes contactarme por cualquiera de las vías disponibles, o dejando tus comentarios al final de este post. También puedes sugerir que temas o post te gustaría leer a futuro.