Mostrando las entradas con la etiqueta objetos. Mostrar todas las entradas
Mostrando las entradas con la etiqueta objetos. Mostrar todas las entradas

Pasar objetos por sesión

Como no es la primera vez que me lo han preguntado, y tampoco es la primera vez que veo esta duda en un foro, les agrego un ejemplo sobre el tema. ;-)

En sí, la única "complejidad técnica", más que nada asociada a la falta de experiencia en cómo trabaja PHP, es que debemos siempre requerir los fuentes de la clase del objeto en cuestión, y particularidad mediante, antes de iniciar la sesión.







No hace falta serializar los objetos, las sentencias de sesión ya se encargan de todo el trabajo, ante dudas de cómo trabaja, siempre el manual oficial.

Saludos!

¿Conoces la clase "DateTime"?

Es muy dificil conocer todas las funcionalidades que nos puede ofrecer un lenguaje, ya que leer el manual con el listado de funciones de arriba a abajo es tan divertido como leer la guía telefónica. Generalmente cuando tenemos un problema para resolver vamos a buscar en la sección correspondiente, según el tema, y listo (arrays, matemáticas, strings, etc). Lo importante muchas veces es, no solo saber de memoria, sino, saber donde buscar (o como dice el viejo dicho, "lo más importante es tener el teléfono de quién sabe", aunque esto lo único que hace es que evitemos aprender a valernos por nosotros mismos ;-)).

Siempre creí que la evolución natural de PHP debería ser juntar todas las funciones "sueltas" del lenguaje en formato "estructurado" y agruparlas en clases "base" como tiene cualquier lenguaje 100% Orientado a Objetos (tienen clases como String, Integer, etc, y si usamos un IDE veremos fácilmente toda la lista de métodos disponibles que se aplican a ese contexto concreto).

Nota al margen: hace unos años hicimos un experimento educativo y varios de mis alumnos de mi primer taller piloto a distancia hicieron un pequeño proyecto final que consistía desarrollar clases de tipo "wrapper" que cumplieran este objetivo (siguiendo el API de Java).

Espero que algún día PHP6 o 7 incorpore por defecto este tipo de organización que nos beneficiará a todos los desarrolladores.

De paso les comento que a veces, en raras ocasiones, podemos descubrir en el manual clases que vienen por defecto en PHP, por ejemplo, DateTime:

date_default_timezone_set('America/Argentina/Buenos_Aires');

$date = new DateTime("2009-02-28");
$date->modify("+1 day");
echo $date->format("Y-m-d");

$date = new DateTime("2009-01-01");
$date->modify("-1 day");
echo $date->format("Y-m-d");

// Salida:
//
// 2009-03-01
// 2008-12-31

Y Netbeans detecta todos sus elementos en la ayuda contextual:


Más información (obviamente): Manual Oficial de PHP

PD: y nunca te olvides de conocer las Standard PHP Library (SPL)

Apuntes: "Principios de Diseño Orientado a Objetos"

Volviendo a mis inicios, retomaremos el camino de los artículos que buscan reforzar determinados conocimientos o conceptos que en otras arquitecturas o lenguajes son tan comunes pero que muchas veces son desconocidos en el mundo PHP.

Teniendo en cuenta que PHP5 es una realidad que nos permite pasar a desarrollos más elaborados, con una Orientación a Objetos más robusta, es fundamental saber que existen "principios de diseño" que nos marcan el rumbo.

Aquí mis apuntes sobre estos temas (que en un futuro espero extenderme en detalle):

Principios de Diseño Orientado a Objetos
  1. SRP - Single Responsibility Principle (Principio de Responsabilidad Única)
  2. OCP - Open/Closed Principle (Principio Abierto / Cerrado)
  3. LSP - Liskov Substitution Principle (Principio de Sustitución de Liskov)
  4. DIP - Dependency Inversion Principle (Principio de Inversión de Dependencias)
  5. ISP - Interface Segregation Principle (Principio de Segregación de Interfaces)
Algunos apuntes encontrados en Wikipedia (inglés)
http://en.wikipedia.org/wiki/Single_responsibility_principle
http://en.wikipedia.org/wiki/Open/closed_principle
http://en.wikipedia.org/wiki/Liskov_substitution_principle

1. SRP - Single Responsibility Principle (Principio de Responsabilidad Única)


Enunciado formal: "Una clase debería tener solo una razón para cambiar"

2. OCP - Open/Closed Principle (Principio Abierto / Cerrado)


Enunciado formal: "Entidades de Software (clases, módulos, funciones, etc) deberían ser abiertas para la extensión y cerradas para la modificación"

3. LSP - Liskov Substitution Principle (Principio de Sustitución de Liskov)


Enunciado formal: "Subtipos deben ser sustituibles por sus clases bases"

4. DIP - Dependency Inversion Principle (Principio de Inversión de Dependencias)


Enunciado formal: "los clientes tienden a ser propietarios de las interfaces y aquellos que ofrecen los servicios las implementan"

5. ISP - Interface Segregation Principle (Principio de Segregación de Interfaces)

Enunciado formal: "Clientes no deberían depender de métodos que no utilizan"

Los métodos "getter / setter" o "accesores / modificadores" (revisado 10/2008)

He visto mucha documentación que habla sobre el tema de los métodos "getter / setter", o traducido al castellano los métodos "accesores / modificadores", y la mayoría se va a los extremos, perdiendo de explicar de forma simple la razón de su existencia.

Trataremos de sacarle la "mística" al asunto.

Antes de usar la estrategia de los "set y get" para los atributos

En PHP4 todos los atributos de un objeto son siempre atributos públicos, es decir, cuando creamos una instancia del objeto a partir de la definición de la clase, tenemos acceso completo a cada uno de los atributos, tanto para leerlos como para modificarlos.

Definición de la clase "Usuario"

1
<?php
2
class Usuario{
3 var
$nombre;
4 var
$nombreReal;
5 var
$edad;
6 var
$clave;
7 }
8
?>



Creo el objeto "unUsuario":

$unUsuario = new Usuario();

En este momento el usuario está vacío, pues sus atributos no tienen ningún valor asignado. Por lo tanto, le daremos sentido a este objeto:

1
<?php
2 $unUsuario
->nombre = "eplace";
3
$unUsuario->nombreReal = "Enrique Place";
4
$unUsuario->edad = "33";
5
$unUsuario->clave = "pepe";
6
?>



Inventemos un escenario completamente de fantasía (surrealista diría)

Supongamos ahora que nuestro sistema es mantenido por varios desarrolladores y que una parte del sistema es mantenida por un "estudiante de programación" que decidió unilateralmente que cuando le llegue el objeto "unUsuario" le pondrá siempre el nombre en mayúsculas y le colocará una clave por defecto si esta está vacía.

1
<?php
2 $unUsuario
->nombre = strtoupper($unUsuario->nombre);
3
4 if (
is_null($unUsuario->clave)){
5
$unUsuario->clave="clavePorDefecto";
6 }
7
?>



Nosotros, como "desarrolladores experimentados", nos sentimos molestos por la tontería que acaba de hacer el "estudiante"... ahora la pregunta es, como evitamos que esto suceda?

Uno de los problemas aquí es que PHP4 no soporta la definición del "alcance" (o también llamada "visibilidad") de los atributos y métodos, algo habitual en cualquier lenguaje serio de tipo "Orientado a Objetos". Esto hace que -aunque no nos guste- el desarrollador de turno pueda hacer lo que quiera con los atributos de cualquier objeto a su alcance.

Entonces migremos a PHP5

PHP5, consciente de este problema, implementa la definición de "visibilidad" de los atributos y métodos, como lo haría Java o .Net. Si hiciéramos una migración "mecánica" de nuestro código, este cambiaría la sintaxis a esta forma (ya que la sintaxis "var" pasa a desuso y esta definía a los atributos siempre "públicos"):

1
<?php
2
3
class Usuario{
4 public
$nombre;
5 public
$nombreReal;
6 public
$edad;
7 public
$clave;
8 }
9
10
?>



Ahora disponemos de las siguientes opciones gracias a la nueva sintaxis: public, private y protected.

Ahora bien, si queremos que el "estudiante" no pueda modificar nuestros datos, podemos pasar a colocar todos los atributos como "private":

1
<?php
2
class Usuario{
3 private
$nombre;
4 private
$nombreReal;
5 private
$edad;
6 private
$clave;
7 }
8
?>



Pronto, ahora cuando el "estudiante" quiera ver o modificar un atributo, el sistema le enviará un error. El problema ahora es que nosotros queremos que:
  1. La edad se pueda saber y cambiar en todo momento.
  2. Se pueda saber el nombre del usuario, pero no modificarlo
  3. No nos interesa que se sepa el nombre real del mismo
  4. Pero queremos que pueda colocar una nueva clave si el usuario se la olvida, pero no saber la que existe actualmente

Esto no lo podemos hacer ni teniendo todos los atributos públicos como sucedía con PHP4 ni restringiendo toda la visibilidad como nos permite ahora PHP5.

¿Cómo se hace entonces?

Por un tema de principios de la POO los atributos de los objetos deben ser siempre "privados" (concepto "encapsulación": no son accesibles desde fuera del objeto, solo el objeto tiene la potestad de usarlos directamente) y se deberán crear métodos públicos que sustituya una u otra operación, o ambas, cada vez que la situación lo amerite: un método "setter" para "cargar un valor" (asignar un valor a una variable) y/o un método "getter" para "retornar el valor" (solo devolver la información del atributo para quién la solicite).

Requerimiento 1) la edad se puede acceder y modificar en todo momento, por consiguiente se deben agregar los dos métodos, un "get" y un "set" para ese atributo:

1
<?php
2
class Usuario{
3 private
$nombre;
4 private
$nombreReal;
5 private
$edad;
6 private
$clave;
7
8 public function
getEdad() {
9 return
$this->edad;
10 }
11 public function
setEdad($edad){
12
$this->edad = $edad;
13 }
14 }
15
?>



Pronto, ahora el atributo se puede consultar o modificar no directamente, solo a través de los métodos "get / set". En este caso no se nota la utilidad, pero pasemos al siguiente requerimiento.

Requerimiento 2) poder saber el nombre del usuario pero no modificarlo, para eso hay que agregar solo un método get para ese atributo:

1
<?php
2
3
class Usuario{
4 private
$nombre;
5 private
$nombreReal;
6 private
$edad;
7 private
$clave;
8
9 public function
getEdad() {
10 return
$this->edad;
11 }
12 public function
setEdad($edad){
13
$this->edad = $edad;
14 }
15 public function
getNombre(){
16 return
$this->nombre;
17 }
18 }
19
?>



Ahora se puede consultar el nombre pero no modificar, pues el atributo no es visible desde fuera del objeto, solo a través de los métodos públicos que vamos definiendo.

Requerimiento 3) no nos interesa que se sepa el nombre real del usuario

Lo dejamos como está y queda inaccesible desde fuera del objeto.

Requerimiento 4) queremos que pueda colocar una nueva clave si el usuario se la olvida, pero no saber la que existe actualmente

Para eso, hacemos lo contrario que con el atributo nombre, agregamos un método "set" pero no el "get":

1
<?php
2
class Usuario{
3 private
$nombre;
4 private
$nombreReal;
5 private
$edad;
6 private
$clave;
7
8 public function
getEdad() {
9 return
$this->edad;
10 }
11 public function
setEdad($edad){
12
$this->edad = $edad;
13 }
14 public function
getNombre(){
15 return
$this->nombre;
16 }
17 public function
setClave($clave){
18
$this->clave = $clave;
19 }
20 }
21
?>



Pronto, usando simples métodos podemos reforzar el diseño de nuestro objeto, restringiendo según nuestra necesidad el acceso a sus atributos.

Formalicemos: "Getter/Setter es solo un tema de conceptos"

Cuando empezamos a aprender a usar Objetos el primer error que cometemos es dejar todos los atributos públicos, lo que permite que cualquier usuario de nuestra clase pueda hacer y deshacer sin control nuestro objeto (modificando y consultando sus valores).

Generalmente nuestros objetos deberían contener determinada información que no necesariamente el usuario de nuestro objeto debería saber, porque no conviene, o porque directamente no corresponde y permitirle acceder a la misma es aumentar innecesariamente la complejidad del uso del objeto.

Regla: "Evitar que el objeto muestre detalles de su implementación"

Otro ejemplo: si tu sabes que tu objeto "Persona" tiene una fecha de nacimiento y calculas su edad, no deberías poder permitir que alguien "de afuera del objeto" cambie la edad, pues está relacionada con otra información (fecha de nacimiento) y a partir de ella es que se genera (calcularEdad()). Lo correcto sería modificar la fecha de nacimiento para que el propio objeto la vuelva a calcular.

Los detalles del funcionamiento del objeto son internos, y el usuario del objeto (otro desarrollador u otro sistema) no debe ni necesita conocerlos. Por consiguiente ya tenemos otro caso claro, el atributo "edad" no debería poder ser modificado externamente, pero sí consultado cada vez que se necesite. Si este fuera un atributo público sería imposible restringir una operación y habilitar la otra. De ahí que nace el concepto de "getter / setter", o de "métodos accesores / modificadores", o como muchos autores se refieren a estos métodos especiales como "propiedades" (pero creo que puede generar confusiones con el concepto "atributo", pues muchos otros autores usan las mismas palabras indistintamente).

Si tú colocas atributos privados, estos serán solo "vistos / accedidos / usados / modificados" dentro de la propia clase. Si tu quieres que puedan ser accedidos desde fuera de la clase, debes crear métodos públicos que internamente "accedan" a los atributos, pero que los dejarán "resguardados" dentro del objeto (no hay que olvidar que en un caso pueden hacer una operación u otra, no necesariamente ambas).

Recalco, digo "nomenclatura", puesto que los nombres de los métodos pueden llamarse como quieras, pero si cumplen con ambas definiciones (get/set), complirá con la esencia de la funcionalidad. El tema es, por convención, se tiende a reconocer así a los métodos que solo sirven para "hacer operaciones básicas como si trabajáramos con atributos públicos", y que además, no deben tener más complejidad que esa. De lo contrario, ya sería mejor que crearas un método comunes y corriente, asignándole un nombre claro a su acción.

Errores más comunes

Definir todos los "get" y "set" para todos los atributos existentes. Es casi lo mismo que si fueran todos públicos, careciendo de utilidad. Lo habitual es que esto no suceda, cuanto más escondamos de nuestro objeto mejor será, pues disminuimos la complejidad de su uso y evitamos que cambie a un estado que no queremos, y cuando menos se sepa de como trabaja internamente, más fácil será poder reutilizarlo en contextos distintos (deberá ser raro que debas dejar disponible todo y no existan algunos que sean solo de uso interno).

Otro error común es agregarle más lógica que asignar un valor o retornar el valor del atributo. Si necesitas agregarle lógica, ya dejan de ser "get / set", lo cual es mejor que cambiemos de nombre y lo dejemos con los demás métodos comunes de nuestra clase.

Por ejemplo: si para cambiar el nombre del usuario, antes de asignar el valor voy a la base de datos y verifico que no exista otro igual, y luego en caso de nombre duplicado genero otro alternativo, etc, yo preferiría o desglosar el método setNombre en varias llamadas a métodos privados, o directamente crear un método nuevo que se llame cambiarNombre, reflejando un proceso fuera del simple get/set.

Nota: esto es muy a nivel personal, hay opiniones encontradas sobre tener una lógica elemental dentro de un set/get o hacerlo tan extenso como necesitemos. Claramente yo estoy en el primer grupo.

Como detalle, para que quede más evidente y visualmente claro

Como todo es convención a la hora de definir la forma de trabajo en un entorno de desarrollo, es habitual que los atributos siempre vayan juntos al principio de la clase e inmediatamente -antes de empezar a definir los métodos- deberían estar los métodos "accesores / modificadores". Lo que se suele hacer, pues son métodos muy simples y generalmente carentes de mucha lógica (como se explica en el punto anterior), tal vez sería mejor hacerlos en una sola línea, sin indentación:

1
<?php
2
3
class Usuario{
4 private
$nombre;
5 private
$nombreReal;
6 private
$edad;
7 private
$clave;
8
9
/** getter / setter */
10
public function getEdad() {return $this->edad;}
11 public function
setEdad($edad){$this->edad = $edad;}
12
13 public function
getNombre(){return $this->nombre;}
14
15 public function
setClave($clave){$this->clave = $clave;}
16
17 }
18
?>


Nota: De todas formas no tomar esto más de un ejemplo, ya que el estándar oficial de condificación para PHP (el que define la empresa Zend) no sugiere en ningún momento esta práctica.

En resumen

El tema no es tan complejo, de forma genérica esta es la explicación de qué es "getter/setter" y para qué sirve y cómo se usan.

También quiero destacar que a pesar de existir esta técnica, no quiere decir que deba ser usada o que su uso esté completamente permitido. Hay que entender que la POO no debería hacer uso de de los getter y setters ya que tendríamos acceso de forma directa al "estado del objeto" (la información que tienen los atributos de un objeto) y permitir el acceso o modificación genera el mismo efecto de manipulación que si fuera una operación de "corazón abierto". Nuestro objeto debería estar protegido del exterior y no permitir tener acceso directo a sus atributos, y trabajar siempre sobre sus métodos ("los métodos definen el comportamiento del objeto"). En caso de no poder hacerlo, se podría priorizar disponer de "get" (obtener valor de un atributo de forma directa) y no "set" (modificar un valor directo de un atributo), y en el peor de los casos, tener un uso muy controlado de los "set".

Para más información sobre diseño OO, discusiones teóricas, buenas prácticas, etc, consultar escritos de gurúes como Martín Fowler.

Artículo basado en una respuesta dada en Foros del Web

Consideraciones sobre el uso del Patrón Singleton desde un entorno web con PHP

Uno de los usos habituales del Patrón de Diseño Singleton es concentrar en un único objeto todas las llamadas a la base de datos y que este se encargue de que nuestro sistema use una única conexión, compartida por todos los que la necesiten.

La lógica del patrón es simple

La lógica es simple, la primera vez que alguna parte de nuestro sistema necesita conectarse a la base de datos, se le pide una instancia de conexión al Singleton implementado en nuestra clase de Persistencia (una clase que separa nuestro código de "lógica de negocio" del código explícito para trabajo con base de datos). Si en las siguientes peticiones esta instancia existe, el Singleton devuelve siempre la misma, así se reutiliza sin crear nuevas.

Ventajes del uso del patrón

Esto evita que nuestro sistema, en un momento dado, tenga innumerables y descontroladas conexiones a la base de datos, consumiendo recursos y tal vez, el máximo permitido por vez (configurado en la misma base de datos). A su vez, al tener todas las conexiones centralizadas, podemos implementar todo tipo de controles y auditorías (registrar cantidad de conexiones, que partes de nuestro sistema realiza más conexiones, horarios para las mismas, etc, etc).

El problema

Lo habitual en "sistemas de escritorio" (no web) es que esta instancia se mantenga generalmente durante toda la vida del sistema, lo cual sería acertado decir que la instancia reutilizada de conexión es siempre la misma (única). Pero en ambientes web, el contexto es distinto y la forma de trabajo cambia.

Por esta razón es muy común que se repita la siguiente consulta en foros:

"Una vez ejecutado el patrón en un página/fuente/scripts, los objetos se destruyen, desapareciendo la instancia del Singleton. Por lo que si se ejecutara nuevamente, todo volvería a repetirse de cero, y no se aprovecharía en toda la aplicación, solo por página."

El problema es ese, el mundo "stateless" ("estado desconectado") de la web, donde queda claramente evidenciado al intentar implementar el patrón "Singleton".

Cuando tu estás, por ejemplo, en una aplicación desktop hecha en Java, tu código está siempre corriendo, de forma permanente. Si tu creas una conexión con la base de datos, siempre estará ahí mientras viva la aplicación (o te desconecte el servidor de base de datos, etc), y cada vez que invoques el "singleton" este funcionará correctamente en todos los casos.

En situaciones "típicas" de la web (sin las conexiones persistentes), luego de terminar la ejecución de un página, pasamos al "estado desconectado" y perdemos todos los objetos. En este contexto, solo tendría sentido el "singleton" si tu página debe hacer llamadas a varios objetos que tienen acceso a la base de datos y tu quieres tener control sobre estos accesos.

Pero luego de concluida la página (terminamos de ejecutar la última línea de nuestro php) terminó la función del "singleton", y el próximo contexto será una nueva ejecución de la página, esta misma u otra distinta.

Conclusiones finales

Resumiendo, serían:

"Se puede implementar perfectamente el patrón Singleton con PHP, pero por el contexto web, este se aplicará normalmente durante la vida de una única página, a menos que implementemos algún mecanismo para persistir el objeto Singleton y así lograr que este perdure durante toda la vida de la aplicación web"

Estas son mis conclusiones aplicadas al mundo PHP desde el mundo Java; si no les gustan, tengo otras

Artículo basado en una respuesta que di en Foros del Web:

Introducción: Cómo traducir de UML a PHP5 (I)

Estoy viendo muy seguido en foros que frecuento regularmente a muchos programadores que quieren dar "el gran salto" y evolucionar desde la programación estructurada hacia la programación orientada a objetos. El error más común que percibo es la falta completa de conceptos base, seguida de una pobre lectura de ejemplos sintácticos que no ayudan a comprender cómo verdaderamente se usan los objetos y cómo hacer para interactuar con ellos.

Estoy fervientemente convencido que enseñar conceptos de POO sin ayuda de UML es elegir el camino más empinado para el novicio. Cuando de abstracciones se trata, el cerebro trabaja mejor jugando con "imágenes", creando simples representaciones de lo que llamamos objetos y sus relaciones (tema que trataremos en otro artículo).

Bueno, no perdamos más tiempo y solucionemos esta carencia en 6 pasos concretos ;-)


Introducción: Representación de una clase

Una clase se representa con un "rectángulo" dividido en 3 zonas horizontales:
  • La primer zona se utiliza para colocar el nombre de la clase. Por convención los nombres de las clases inician con la primera letra en mayúsculas, y todas en singular (Persona, Cliente, Vendedor, Perro, Fruta, etc)
  • La segunda zona se utiliza para colocar la lista de atributos. Cada atributo iniciará con un símbolo que representará la "visibilidad" del mismo, que podrá ser "público" (+), "privado" (-) o "reservado" (#).
  • La tercer zona se utiliza para colocar los métodos de la clase. Cada método, igual que sucede con los atributos, deberá tener los mismos símbolos de "visibilidad" que se aplican con los atributos.
Se dice que la "zona de atributos" representa el estado actual del objeto (que cambiará según los valores que pueda tener en un momento dado) y la "zona de métodos" el comportamiento del mismo (dice qué puede hacer, qué se puede cambiar del mismo, qué se le puede preguntar, etc), configurando una suerte de "interfaz" que permitirá que otros objetos puedan interactuar con él (los objetos interactúan con otros objetos a través de sus métodos).

En este ejemplo podemos observar además que para cada atributo o método deberemos definir cual será el tipo de valor que manejará (String, Date, Integer, etc), no importando verdaderamente si nuestro lenguaje lo soporta en un 100%.

No hay que olvidar que UML es un lenguaje de modelado que permite comprender los diseños sin tener que llegar a conocer el código, y la traducción no está atada a ningún lenguaje de programación. Si el lenguaje es OO, se puede traducir, y tal vez, algunos detalles menores queden por el camino, pero que no debería afectar al concepto general de lo que se quiere transmitir.

Por ejemplo, PHP es un lenguaje de "tipado dinámico" (o lo opuesto a decir "tipado fuerte") donde según la asignación de valores (o su contexto de uso) define el tipo de la variable. Para el caso de la traducción del UML, cada vez que veamos el "tipo", este dato nos servirá como documentación sobre qué información manejaremos internamente, pero no se traducirá en código explícito (porque el lenguaje no lo provee).

Nota: por eso muchos critican a PHP en general. Al no tener un "tipado fuerte" no lo consideran un lenguaje orientado a objetos "robusto" (al existir menos controles sobre los valores que manejan las variables). Según el autor de PHP, esto es una ventaja del lenguaje -la flexibilidad- y juega en favor de los programadores, no en contra.

Paso 1) "Nombre del archivo"

Normalmente usamos un nombre seguido de la extensión: prueba.php. En el caso de los objetos, hay muchas opiniones al respecto. La mayoría de los autores sugiere diferenciar un archivo que define una clase de un archivo que usa varias clases predefinidas.

He visto autores que usan la siguiente nomenclatura: class.NombreDeLaClase.php.

En mi caso, yo siempre me sentí más cómodo usando NombreDeLaClase.class.php y así sigo manteniendo la estrategia de no alejarme mucho de Java para contar con un modelo de referencia para poder aprender de él.

La única ventaja que encuentro en la primera opción es que si listamos todos los archivos de un directorio, todos los que empiecen con "class." estarán juntos.

Para seguir el ejemplo, mi ejemplo, usaremos: Persona.class.php

Paso 2) "Definir la clase"

Aquí debemos ceñirnos a la sintaxis del lenguaje de turno al cual queremos convertir desde un diagrama UML. En nuestro caso, es PHP5, por lo cual solo debemos ir hasta el manual, buscar la parte donde hablan de creación de clases y hacer la siguiente conversión mecánica.

Nota: si usamos Eclipse como IDE para desarrollar, al momento de decirle "crear nuevo archivo php" y colocarle de nombre ".class.php", nos arma un esqueleto más completo de forma totalmente automática ;-)

Paso 3) "Definir los atributos"

Si ya tenemos el esqueleto principal, solo debemos leer uno a uno los atributos del UML y pasarlos a código casi de forma directa:
Como comentaba, no tenemos que preocuparnos de no disponer de un "tipado fuerte" (como sucede con Java) que nos obligue a escribir en la definición de atributos de que tipo son.
Podemos aplicar algunas "sutilezas" pero que en realidad no aportan mucho valor:

private $nombre="";

Con esta asignación estamos diciendo que el atributo es de tipo String.

En este caso, y para PHP, el tipado en el UML nos aporta información extra para la documentación de nuestro sistema (por lo cual no hay que obviarla a la hora de diseñar, aunque nuestro lenguaje no lo soporte explícitamente).

Paso 4) "Definir los métodos"

Siguiendo el mismo razonamiento que el usado en el caso anterior con los atributos, los métodos deben definir también su visibilidad:

Paso 5) "Definir un constructor"

Generalmente, aunque esto es flexible, en un diagrama UML que representa una clase no hace falta agregar como método el propio constructor de la clase; en sí, se sobreentiende que constará de uno y no aportaría nada nuevo a la documentación del diseño (de la misma forma que sucedería con los métodos "getter" y "setter", que hablaremos en otro artículo).

Como los atributos son "privados" (no se tiene acceso a los mismos desde fuera de la clase) para poder asignarles valores iniciales en el momento justo de la creación, deberemos crear un método constructor:

Recibimos los 3 parámetros desde el constructor y luego los asignamos a los atributos de la clase.

Este método se ejecuta "automáticamente" cuando hacemos un "new" para crear una instancia a partir de la clase (que se ve en el próximo paso).

Paso 6) "Probarlo"

Creamos la clase, usando el constructor, para luego usar un método del objeto.


Este ejemplo, en realidad, no imprimirá la edad del "vendedor", puesto que para simplificar el ejemplo y no agregar "ruido" al código (¡si habré visto libros con códigos innecesariamente complejos!), no está implementada la fórmula para calcular la edad a partir de la fecha de nacimiento ingresada (pero creo que la idea general se entiende).


Resumen final

Fuimos viendo paso a paso como se traduce a PHP5 la representación en UML de una clase definida en el contexto de la programación orientada a objetos. Conocimos las 3 zonas que definen una clase (nombre, atributos y métodos), la visibilidad (métodos y atributos), el constructor (para definir un comportamiento al crear el objeto) y finalmente, como probar la clase creada.

¿Dudas o sugerencias? Bienvenidas en los comentarios de este artículo ;-)

Artículo basado en una respuesta que di en Foros del Web

Actualización (27/07/2006): las capturas de pantallas están hechas sobre las siguientes herramientas: la versión "comunitaria" (gratuita) de Poseidon (basado en el proyecto libre ArgoUML) y Eclipse (usando el paquete EasyEclipse for PHP).

Entradas populares