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

viernes, 11 de noviembre de 2011

PHP 5.+ el C++ de la web

Me parece una analogía interesante este título, porque C++ es uno de los lenguajes de programación mas extendidos de geográficamente hablando y en lo que a usos y aplicaciones compete. Casi cualquier software que podamos imaginarnos que utilizamos hoy guarda alguna relación con este lenguaje. Esto es porque compiladores, interpretes, maquinas virtuales, frameworks o sistemas operativos esta desarrollado usando C, C++ o algún descendiente o derivado de estos.

Pero el objetivo no es hablar de C++, hablaremos de PHP. Entonces ¿porque la analogía? se preguntaran algunos. Pues básicamente porque PHP es el lenguaje más extendido en la web. Cuando el internet era como el viejo oeste, antes de que se descubriera el oro en el, PHP hacia su debut en este terreno. La evolución de PHP me parece un tanto curioso ya que nace para la web y luego se va convirtiendo en un lenguaje de propósito general. Casi la mayoría de los lenguajes de programación ha seguido un curso inverso al de PHP, desde lenguaje de propósito general hasta desarrollar extensiones o versiones para web. Mucho de lo que se usa en la web esta escrito en parte en PHP, entre esto encontramos paneles de administración, clientes de bases de datos, clientes de correos, servicios de datos, gran parte de nuestras páginas favoritas, CMS, etc.. para darnos una idea.

Un dato curioso

Casi siempre que me encuentro con un viejo desarrollador que programa con PHP noto en el una cierta resistencia al uso de las nuevas características del lenguaje. Las encuentra poco relevantes o simplemente no esta interesado en ello. Es como si para ellos el tiempo se hubiese congelado en la evolución de este lenguaje, y avocan siempre por sus ancestros menos evolucionados. Pues les tengo una noticia, la extinción es algo inminente, porque es el curso que toma todo en el mundo, desde los seres vivos hasta la tecnologías se ven relegados por sus versiones mejor adaptadas, y el rechazar esta realidad nos convierte en parte del conjunto destinado a extinguirse. No digo que no haya que saber de lo que precede a lo actual, "nunca hay que olvidar de donde se viene", pero al igual que la vida en nuestro entorno de trabajo no podemos vivir en el pasado mientras el mundo exterior continua su marcha.


Continúan las semejanzas

Dirán algunos ¿en que se parece PHP a C++? Pues les diré que tienen algunas características comunes. Ambos soportan programación procedimental, funcional y orientado a objetos, aunque hay diferencias en la forma en que implementan la orientación a objetos dado que este desarrollo de PHP se ha visto más influenciado por lenguajes como Java. Al igual que C y C++, PHP cuenta con un gran conjunto de librerías y extensiones para todo tipo de interacciones, servicios web, interacción con el shell del sistema operativo, manipulación de archivos, edición de imágenes, tratamiento y manipulación de cadenas y más.

Creo que una de las grandes ventajas de en lo que a funcionalidad se refiere es el número de librerías para interacción con bases de datos. En este sentido el desarrollo de PDO puede darle una ventaja más en esto al pasar de muchos controladores para cada SGBD a una capa de abstracción de acceso a datos más ligera y fácil de implementar para cada manejador, es lo que JDBC en Java, provee por ahora menos funciones pero permite una interacción mas limpia y resulta fácil de migrar. Algunos aducirán que MDB solucionaba esto, pero esto es algo que no es un script es parte del lenguaje en si mismo, así que dejemos de intentar reinventar la rueda.

Otras de las similitudes es que PHP esta disponible en casi todas las plataformas, puede bien ser usado como interprete o como modulo con un servidor web entre estos IIS y Apache. es decir que pueden correr sus programas en donde sea. Gracias a algunas extensiones es posible programar aplicaciones de escritorio utilizando PHP GTK.

El soporte para programación orientada a objetos es relativamente reciente, en las últimas versiones estables disponibles, estas características están bastante maduras. Aunque para aquellos que conocieron como se trabajaba con clases y objetos ne la versión 4 se darán cuenta de que es algo muy distinto en versión 5 o superior. Pero no es mi objetivo mostrar acá las nuevas características del lenguaje, es mejor si eso lo investigan uds. mismos consultando el manual siempre disponible en php.net. Hablaremos sin embargo de algunas de las características y tecnologías prometedoras y algunos buenos y malos hábitos.



Dejando los malos hábitos


Otras de las semejanzas PHP - C++ es que si no se tienen buenos hábitos de programación y codificación, y no suele documentar mucho su código, el mantener y depurar un programa o modulo puede resultar una tarea infernal. Para los que han trabajado con C o C++ se darán cuenta de que muchos de los errores provienen de aspectos mal gestionados o no gestionados por el programador como la memoria, los tipos de datos, lo valores contenidos en  las variables en un momento dado y otros. En PHP se tienen casi una cantidad de problemas semejante, el hecho de que PHP sea un lenguaje débilmente tipado conlleva una cantidad de problemas con ello, es una arma de doble filo.

Por ejemplo, si bien puedo utilizar una variable para contener distintos tipos de dato al realizar operaciones con la misma necesito validar el tipo de dato contenido, su previa declaración y existencia, para saber si es posible o no aplicarle o utilizarla con una función en particular. Igualmente el retorno de funciones y métodos no tiene un tipo especifico, si lo tiene. con lo que no se puede tener certeza del resultado o del valor retornado, si se desea utilizar posteriormente. Existe ademas una cierta cantidad y tipos de errores que pueden producirse en tiempo de ejecución que no causan un termino o la no ejecución de un bloque de código, lo que puede resultar en que se llegue a un resultado no deseado o se desencadene un error que se pueda frenar la ejecución.

Análogo a los punteros de C++ en PHP el uso extensivo de matrices es uno de sus grandes potenciales y también una de los grandes problemas, por falta de una correcta gestión. Debemos tener presente siempre que en entornos de producción hay limites a la cantidad de memoria disponible, aunando a esto el uso incorrecto de las claves se pueden llegar a tener muchos problemas al usar matrices. PHP no es Fortran en lo que a gestión de matrices y potencia de cálculos vectoriales se refiere, pero cuenta con una gama de funciones bien surtida para la manipulación, búsqueda y ordenación ser refiere.

Otra mala práctica, remanente en unos pocos programadores, es el embeber html  u otro código dentro del script php. He dicho embeber html en el php y no embeber php en el html que resultan dos cosas diferentes, algo que algunos terminan confundiendo. El embeber es una práctica que debe limitarse al mínimo posible. No solo porque no es "elegante", sino porque ya hay motores de plantillas más o menos maduros que facilitan esto, porque facilita el dar mantenimiento al código y separar nuestras capas de datos o modelo de negocios de nuestra capa de presentación, hace mas simple los desarrollos futuros.

Debemos aprender a escuchar y poner en práctica las recomendaciones de Zend y la comunidad de desarrolladores. Si una función esta obsoleta, créalo es obsoleta y use el reemplazo. Si se dicen que una determinada variable es el remplazo de otra úsela en sus programas. Si esta usando una versión de PHP no intente hacerlo funcionar como una versión inferior a menos que sea absolutamente necesario. Al menos lea las referencias de funciones, novedades y diferencias de la versión que utiliza. Usemos las cosas para lo que son y como debe ser, las expresiones booleanas deben recibir valores o expresiones booleanos, los que lo hacen saben de lo que les hablo, usar variables no definidas, con valores nulos, numéricos o de cadena cuyo valor pueda ser evaluado como booleano. Se deben usar los tipos de dato correctamente, validar o forzar su tipo si es necesario y evitar las asignación de datos de otro tipos en esas variables. Debe tenerse presente la versión para la que se esta escribiendo el código. A partir de PHP 5 existe un nuevo nivel de error E_STRICT que incluye tipos de errores de tipo estricto de la versión esto puede ayudarnos a detectar y corregir aquellos segmentos en que estamos usando código no acorde a las últimas versiones estables, también esta disponible la función version_compare que algunos herramientas CASE incluyen en el código generado para validar la ejecución del en dependencia de la versión del interprete.

Aprendamos a trabajar con objetos, como debe ser. No mezcle sintaxis de versiones diferentes.  Establezca el tipo de objetos en los argumentos de los métodos. Saquemos provecho real de características como la visibilidad, la unificación de constructores y los métodos especiales, asignemos los valores por defecto a los parámetros que puedan ser opcionales. Dejemos de usar los objetos como arreglos, prácticas como la asignación y uso de atributos no declarados no son recomendables. Procuremos mantener separadas nuestras capas de presentación, modelo de negocios y acceso a datos. Saquemos máximo provecho de los paradigmas de programación soportados por el lenguaje utilizando el tipo adecuado al contexto o problema solucionar.

Buenas prácticas

Finalmente creo que estos dos lenguajes (PHP y C++) si tienen varias similitudes, no solo en los problemas que se presentan al programar con ambos, sino también en las bondades que cada uno provee. PHP es un lenguaje con gran potencial, pero al igual que las demás cosas creadas por el ser humano todo depende del uso que se le de. Con el Objetivo de que mejoren en los aspectos que necesiten les dejo un par de enlaces donde pueden explorar las mejoras prácticas que cada quien puede usar en sus proyectos o en su estilo de programación. Mejores prácticas de desarrollo en PHP, Guía de buenas practicas en PHP, Manual de phpDocumentor, Zona PHP - ¿Qué esperar de PHP 5 ?.

jueves, 15 de enero de 2009

Conceptos básicos de orientación a objetos


La orientación a objetos se basa en los siguientes conceptos elementales, que facilitan el abstraer los diferentes:

Clase
Objeto
Atributo
Método
Herencia
Polimorfismo
Encapsulamiento


Clases e instancias

Una Clase es un conjunto de objetos que comparten una estructura y comportamiento comunes. En el mundo real, normalmente tenemos muchos objetos del mismo tipo. Por ejemplo, nuestro teléfono celular es sólo uno de los miles que hay en el mundo. Si hablamos en términos de la programación orientada a objetos, podemos decir que nuestro objeto celular es una instancia de una clase conocida como "celular". Los celulares tienen características (marca, modelo, sistema operativo, pantalla, teclado, etc.) y comportamientos (hacer y recibir llamadas, enviar mensajes multimedia, transmisión de datos, etc.). Podemos extrapolar esta concepto a cualquier conjunto ya sean entidades tangibles o abstracciones, reales, imaginarias, etc.

Las clases nos permiten tener todas las características y comportamientos (las variables y métodos) en una sola entidad,  algo que en los lenguajes estructurados esto era imposible. A esto se le conoce como encapsulamiento y lo abordaremos más adelante.

Entonces ¿qué es un objeto? Entender que es un objeto es la clave para entender cualquier lenguaje o método orientado a objetos. Un objeto representa un ítem individual e identificable, o una entidad real o abstracta, con un papel definido en el dominio del problema. Un objeto no es un dato sino una instancia de una clase, contiene en su interior cierto número de componentes bien estructurados. Es posible intercambiar los términos objeto o instancia, los objetos son pues ejemplares de una clase cualquiera. La estructura y el comportamiento de objetos similares se definen en sus clases comunes.

Un objeto dado se caracteriza por tener:
  1. Estado
  2. Comportamiento
  3. Identidad

El Comportamiento es como un objeto actuá y reacciona, en términos de sus cambios de estado y de los mensajes que intercambia. El Estado de un objeto representa los resultados acumulados de su comportamiento. Los Objetos de Software mantiene sus características (identidad) en una o más "variables" o "atributos" (su estado), e implementa su comportamiento con "métodos" mediante los que interactúa con otros objetos o altera sus propios atributos.

La Identidad es la propiedad de un objeto que lo lleva a distinguirse de otros. En programación la identidad de los objetos sirve para comparar si dos objetos son iguales o no. En muchos lenguajes de programación la identidad de un objeto esté determinada por la dirección de memoria de la computadora en la que se encuentra el objeto.



La API, Atributos y Métodos

Un Atributo es una variable, un contenedor de algún tipo de dato asociado a la clase. Los valores de los tributos pueden ser alterados por la ejecución de algun método.

Método: es un término utilizado en algunos lenguajes de programación para referirse a algún comportamiento de los objetos de una clase, un algoritmo asociado a una clase que se desencadena después de recibir un mensaje. Es lo que el objeto puede hacer.


Características de la Programación orientada a objetos (POO)

La Herencia es el mecanismo fundamental de relación entre clases en la orientación a objetos. Relaciona las clases de manera jerárquica; una clase padre o superclase sobre otras clases hijas o subclases. Es decir que una clase puede heredar sus variables y métodos a varias subclases. Por tanto la subclase, aparte de los atributos y métodos propios, tiene incorporados los atributos y métodos heredados de la superclase. Los métodos heredados pueden ser polimorfos, de forma que las subclases pueden responder de forma diferente al mismo mensaje que se envía a su clase base. De esta manera se crea una jerarquía de herencia, una jerarquía de clases cada vez más especializada.

En la orientación a objetos, se consideran dos tipos de herencia, simple y múltiple. En el caso de la primera, una clase sólo puede derivar de una única superclase. Para el segundo tipo, una clase puede descender de varias superclases.

Algunos lenguajes orientados a objetos, como C++ permiten herencias múltiples, lo que significa que una clase puede heredar los atributos de otras dos superclases. Este método puede utilizarse para agrupar atributos y métodos desde varias clases dentro de una sola.

En otros lenguajes, como Java, sólo se dispone de herencia simple, para una mayor sencillez del lenguaje, si bien se compensa de cierta manera la inexistencia de herencia múltiple con un concepto denominado interface.

La herencia ofrece una ventaja importante, permite la reutilización del código. Una vez que una clase ha sido depurada y probada, el código fuente de dicha clase no necesita modificarse. Su funcionalidad se puede cambiar derivando una nueva clase que herede la funcionalidad de la clase base y le añada otros comportamientos. Reutilizando el código existente, el programador ahorra tiempo y dinero, ya que solamente tiene que verificar la nueva conducta que proporciona la clase derivada. 


La palabra Polimorfismo proviene del griego y significa que posee varias formas diferentes. Así como la herencia está relacionada con las clases y su jerarquía, el polimorfismo se relaciona con los métodos. Es la capacidad que tienen los objetos de una clase de responder al mismo mensaje o evento en función de los parámetros utilizados durante su invocación.

 El polimorfismo es una característica que merece un artículo propio, por ahora nos limitaremos a conocer lo tipos. Se puede clasificar el polimorfismo en dos grandes clases:

Polimorfismo dinámico (o polimorfismo paramétrico) es aquél en el que el código no incluye ningún tipo de especificación sobre el tipo de datos sobre el que se trabaja. Así, puede ser utilizado a todo tipo de datos compatible.

Resulta mucho más fácil ilustrar esto con un ejemplo, tomemos un ejemplo utilizando Java.

class Mamifero {
  public void mover() {
    System.out.println("Ahora es un mamifero el que se mueve");
  }
}

class Perro extends Mamifero {
  public void mover() {
    System.out.println("Ahora es un perro el que se mueve");
  }
}

class Gato extends Mamifero {
  public void mover() {
    System.out.println("Ahora es un gato el que se mueve");
  }
}

public class Polimorfismo {
  public static void muevete(Mamifero m) {
    m.mover();
  }
  public static void main(String[] args) {
    Gato bisho = new Gato();
    Perro feo = new Perro();
    muevete(bisho);
    muevete(feo);
  }
}

Vemos que el método “muevete” llama al método mover de un mamífero y aunque no sabe con qué clase de mamífero trata, funciona y se llama al método correspondiente al objeto específico que lo llama (es decir, primero un gato y luego un perro).

Este ejemplo esta relacionado con la ligadura dinamica, termino usado para referirse a ese mecanismo que pospone hasta el momento de ejecutar una llamada, la eleccion del metodo a ejecutar. Gracias a la ligadura dinámica, pueden invocarse operaciones en objetos obviando el tipo actual del éstos hasta el momento de la ejecución del código, es decir que me perite definir elementos como un tipo e instanciarlos como un tipo heredado.

Polimorfismo estático (o polimorfismo ad hoc) es aquél en el que los tipos a los que se aplica el polimorfismo deben ser explicitados y declarados uno por uno antes de poder ser utilizados.
 
Por lo tanto, podemos por ejemplo, definir varios métodos homónimos de addition() efectuando una suma de valores.  
  • El método int addition(int,int) devolvería la suma de dos números enteros.
  • float addition(float, float) devolvería la suma de dos flotantes.
  • char addition(char, char) daría por resultado la suma de dos caracteres definidos por el autor.
 se diferencian entre sí por:

  • La cantidad de parámetros.
  • El orden en que se ubican los parámetros al invocar al método.
  • El tipo de dato de los parámetros.
  • Clasificación

Diferencias entre polimorfismo y sobrecarga

La sobrecarga se da siempre dentro de una sola clase, mientras que el polimorfismo se da entre clases distintas.

Un método está sobrecargado si dentro de una clase existen dos o más declaraciones de dicho método con el mismo nombre pero con parámetros distintos, por lo que no hay que confundirlo con polimorfismo.

La sobrecarga se resuelve en tiempo de compilación utilizando los nombres de los métodos y los tipos de sus parámetros; el polimorfismo se resuelve en tiempo de ejecución del programa, esto es, mientras se ejecuta, en función de que clase pertenece un objeto.


Encapsulamiento

Hay muchos datos que no tiene porque conocerlo aquel que este usando una clase; ya que son inherentes al objeto y solo controlan su funcionamiento interno, es decir el usuario no necesita conocer la implementación. Al evitar que el usuario modifique los atributos directamente y forzándolo a utilizar funciones definidas para modificarlos (llamadas interfaces), se garantiza la integridad de los datos.

Esto es el Encapsulamiento, encapsulación u ocultación. Consiste en el ocultamiento del estado, es decir, de los datos miembro, de un objeto de manera que sólo se puede cambiar mediante las operaciones definidas para ese objeto. El aislamiento protege a los datos asociados a un objeto contra su modificación por quien no tenga derecho a acceder a ellos, eliminando efectos secundarios e interacciones.
El encapsulamiento es muy conveniente y nos permite colocar en funcionamiento nuestro objeto en cualquier tipo de sistema, de una manera modular y escalable.
La encapsulación da lugar a que las clases se dividan en dos partes:
  • Interface: captura la visión externa de una clase, abarcando la abstracción del comportamiento común a los ejemplos de esa clase.
  • Implementación: comprende la representación de la abstracción, así como los mecanismos que conducen al comportamiento deseado.
La encapsulación define los niveles de acceso para elementos de la clase. Estos niveles de acceso definen los derechos de acceso para los datos, permitiéndonos el acceso a datos a través de un método de esa clase en particular, desde una clase heredada o incluso desde cualquier otra clase. En forma general la visibilidad se aplica tanto a métodos como atributos. Cada lenguaje implementa la forma de aplicar el principio de ocultación.

Existen tres niveles de acceso:
  1. Privado: Son los elementos que solo pueden ser accedidos directamente por la clase que los define. El símbolo usado para su representación es el menos "-".
  2. Protegido: Los elementos protegidos son aquellos que pueden ser accedidos por las clases descendientes o clases que compartan el mismo espacio físico "paquete", "namespace", etc. El símbolo usado es el numeral "#".
  3. Público: Estos son los elementos en los cuales no hay restricción alguna y pueden ser accedidos por cualquier clase y objeto del modelo. El símbolo usado es el más "+".