Solución Semana 4: "Sistema Modular" (III de V)


El punto III de los requerimientos de la Semana 4 decía:

"Clases Abstractas: hacer una lista de todas las clases que no son necesarias instanciarlas en el sistema y que deban ser "abstractas". Explicar la implementación, justificar la selección y la razón de esta decisión."

Veamos algunos conceptos, tenemos la definición de lo que es una Clase Abstracta según Wikipedia:

Clase Abstracta

La herencia permite que existan clases que nunca sean instanciadas directamente. En el ejemplo anterior, una clase "perro" heredaría los atributos y métodos de la clase "mamífero", así como también "gato", "delfín" o cualquier otra subclase; pero que ocurra que en el sistema no haya ningún objeto "mamífero" que no pertenezca a alguna de las subclases. En ese caso, a una clase así se la conocería como Clase Abstracta. La ausencia de instancias específicas es su única particularidad, para todo lo demás es como cualquier otra clase.

También tenemos la explicación técnica según el manual oficial de PHP:

No es permitido crear una instancia de una clase que ha sido definida como abstracta. Cualquier clase que contenga por lo menos un método abstracto debe también ser abstracta. Los métodos definidos como abstractos simplemente declaran el método, no pueden definir la implementación Cuando se hereda desde una clase abstracta, todos los metodos marcados como abstractos en la declaración de la clase padre, deben de ser definidos por la clase hijo; adicionalmente, estos metodos se deben definir con la misma o menor visibilidad.

Bien, ya tenemos los conceptos técnicos definidos, ahora la pregunta sería... ¿cómo las uso? ¿para qué las uso? ¿cuando las uso?

Las estrategias para usarlas, donde usarlas, son:

Solo sirven para ser heredadas por otras clases o para usarlas sin instanciar.

En el primer caso podemos usar la clase como un esqueleto o un molde que permita solo ser heredada con el argumento de que es tan genérica que es poco probable que se use directamente. Por consiguiente siempre heredaremos de ella, como la clase Persona, para crear objetos más especializados como la clase Usuario. Es poco probable que nuestros sistemas necesiten una clase Persona de forma directa, pero sí la usaremos como molde para crear UsuarioAdmin, UsuarioOperador, etc.

En el segundo caso una clase que no tiene atributos, que sirve como "fachada" para esconder otras clases, por consiguiente no tiene sentido que sea instanciada y se puede usar directamente como una clase, ejecutando sus métodos. También podría ser una clase que sirva de "herramienta genérica" que agrupe un conjunto de funcionalidades que usaremos de manera aislada del resto del objeto. Por ejemplo, podríamos tener una clase Fecha que solo tuviera métodos que reciben valores y luego procesan los resultados, sin necesitar atributos para la clase.

Por eso todas las "fachadas" (Patrón Facade) son generalmente abstractas.

Nota: como no hace falta instanciar la clase para invocar un método, creo una clase "abstracta" y ejecuto directamente la clase e invoco su método, evitando crear una instancia, con la ventaja de tener menos código y no reservar memoria para una variable. La otra ventaja, menos visible pero más importante, es que al obligar por código a hacer que la clase sea abstracta estamos reforzando el diseño de nuestro sistema (nadie podrá usar esa clase de forma directa, evitando un error de desconocimiento por parte de los desarrolladores)

¿Qué se pedía en la letra del problema?

El sentido del requerimiento para esta parte era que buscaran clases que fueran candidatas a convertirse en abstractas basándose en la forma de uso o en que directamente no tenían atributos propios, solo un conjunto de métodos que ofrecen una funcionalidad concreta en cada uno de ellos.

Rápidamente podemos concluir que donde se podría pasar a clases abstractas sería en la Capa de Presentación y las clases claramente candidatas son:
  • ConsultarUsuario.class.php
  • ListadoDeUsuarios.class.php
  • MostrarUsuario.class.php
Las tres clases hacen cosas muy concretas y no necesitan tener atributos, perfectamente podrían trabajar de la siguiente forma:

ConsultarUsuario::ejecutar();

En vez de:

$ConsultarUsuario = new ConsultarUsuario();
$ConsultarUsuario->ejecutar();


¿Y la clase Index?

Sí, tal vez, actualmente no tiene mucho sentido pues aunque existen dos atributos (título y texto), perfectamente podría evitarse y pasarlos por parámetros directamente al método ejecutar.

¿Y las clases BaseDeDatos y Persona (ambas del framework)?

Estos últimos casos son una decisión de diseño ajustada a un contexto, donde deberemos pensar qué es lo que queremos desarrollar dentro de esta clase y cómo trabajará nuestro sistema. Por el momento no es tan evidente como los casos anteriores, así que no necesariamente esta clase deberá ser abstracta.

Ya está la planilla actualizada, como así también el repositorio con los fuentes y como siempre, en los comentarios de esta entrada se pueden sacar las dudas sobre este tema :-)

2 comentarios:

Andrés Guzmán dijo...

Gracias Enrique, me quedó mucho más claro, excelente explicación.

Cada vez aprendo más en el taller, a pesar de mis errores.

Muchos saludos.

Enrique Place dijo...

Estimado Guzmán:

Los errores solo son importantes para corregirnos, no para hacer una valoración apresurada de nuestras capacidades.

La idea es aprender en base a ellos.

Vamos, adelante, que dentro de poco ya iniciamos los equipos de trabajo. ;-)

Entradas populares