Ads 468x60px

Perfil

domingo, 17 de febrero de 2013

CĂłmo escribir cĂłdigo que acepte el cambio

Escritura de cĂłdigo, que es fácil de cambiar es el Santo Grial de la programaciĂłn. Bienvenido al nirvana de programaciĂłn! Pero las cosas son mucho más difĂ­ciles en la realidad: el cĂłdigo fuente es difĂ­cil de entender, punto dependencias en direcciones innumerables acoplamiento es molesto, y pronto siente el calor del infierno programaciĂłn. En este tutorial, vamos a discutir algunos principios, tĂ©cnicas e ideas que le ayudarán a escribir cĂłdigo que sea fácil de cambiar.

CĂłmo escribir cĂłdigo que acepte el cambio

Algunos Conceptos de OrientaciĂłn a Objetos

ProgramaciĂłn orientada a objetos (POO) se hizo popular debido a su promesa de organizaciĂłn del cĂłdigo y reutilizaciĂłn, es absolutamente fracasado en este empeño. Hemos estado utilizando los conceptos de programaciĂłn orientada a objetos desde hace muchos años, y aĂşn asĂ­ seguir aplicando repetidamente la misma lĂłgica en nuestros proyectos. OOP introdujo una serie de buenos principios básicos que, si se utilizan adecuadamente, puede conducir a una mejor, cĂłdigo más limpio.

CohesiĂłn

Las cosas que van de la mano debe mantenerse juntos, de lo contrario, deberĂ­an ser trasladado a otro lugar. Esto es lo que el tĂ©rmino, la cohesiĂłn, se refiere. El mejor ejemplo de cohesiĂłn se puede demostrar con una clase:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
clase ANOTCohesiveClass {
   privado $ primerNumero ;
   privado $ secondNumber ;
   privado $ length ;
   privado $ width ;
   funciĂłn __construct ( $ primerNumero , $ secondNumber ) {
      $ This - primerNumero> = $ primerNumero ;
      $ This -> secondNumber = $ secondNumber ;
   }
   funciĂłn setLength ( $ longitud ) {
      $ This - Longitud> = $ longitud ;
   }
   funciĂłn setHeight ( $ height ) {
      $ This -> width = $ height ;
   }
   funciĂłn add () {
      devolver $ this -> primerNumero + $ this -> secondNumber;
   }
   funciĂłn de resta () {
      devolver $ this - primerNumero> - $ this - secondNumber>;
   }
   funciĂłn area () {
      devolver $ this -> longitud * $ this -> ancho;
   }
}
En este ejemplo se define una clase con campos que representan los nĂşmeros y tamaños. Estas propiedades, a juzgar sĂłlo por sus nombres, no van de la mano. Entonces tenemos dos mĂ©todos, add () yresta () , que operan sĂłlo en las dos variables numĂ©ricas. Nos tienen además un Ăˇrea () mĂ©todo, que opera en la longitud y anchura de los campos.
Es obvio que esta clase es responsable de separar los grupos de informaciĂłn. Dispone de cohesiĂłn muy bajo . Vamos a refactorizar.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
clase ACohesiveClass {
   privado $ primerNumero ;
   privado $ secondNumber ;
   funciĂłn __construct ( $ primerNumero , $ secondNumber ) {
      $ This - primerNumero> = $ primerNumero ;
      $ This -> secondNumber = $ secondNumber ;
   }
   funciĂłn add () {
      devolver $ this -> primerNumero + $ this -> secondNumber;
   }
   funciĂłn de resta () {
      devolver $ this - primerNumero> - $ this - secondNumber>;
   }
}
Esta es una clase altamente cohesivo . ¿Por quĂ©? Debido a que cada secciĂłn de esta clase pertenece uno con el otro. Usted debe esforzarse para la cohesiĂłn, pero ten cuidado, que puede ser difĂ­cil de lograr.

Ortogonalidad

En tĂ©rminos simples, la ortogonalidad se refiere al aislamiento o eliminaciĂłn de los efectos secundarios. Un mĂ©todo, de clase o mĂłdulo que cambia el estado de otras clases no relacionadas o mĂłdulos no es ortogonal. Por ejemplo, el cuadro negro de un aviĂłn es ortogonal. Tiene su funcionalidad interior, fuente de alimentaciĂłn interna, micrĂłfonos y sensores. No tiene ningĂşn efecto sobre el aviĂłn en el que reside, o en el mundo exterior. SĂłlo se proporciona un mecanismo para grabar y recuperar datos de vuelo.
Un ejemplo de tal sistema no ortogonal es la electrĂłnica de su coche. Para incrementar la velocidad de su vehĂ­culo tiene varios efectos secundarios, como aumento de volumen de la radio (entre otras cosas). La velocidad no es ortogonal al coche.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
clase Calculadora {
   privado $ primerNumero ;
   privado $ secondNumber ;
   funciĂłn __construct ( $ primerNumero , $ secondNumber ) {
      $ This - primerNumero> = $ primerNumero ;
      $ This -> secondNumber = $ secondNumber ;
   }
   funciĂłn add () {
      $ Suma = $ this -> primerNumero + $ this -> secondNumber;
      si ( $ suma > 100) {
         ( nuevo AlertMechanism ()) - tooBigNumber> ( $ cantidad );
      }
      volver suma $ ;
   }
   funciĂłn de resta () {
      devolver $ this - primerNumero> - $ this - secondNumber>;
   }
}
clase AlertMechanism {
   funciĂłn tooBigNumber ( $ numero ) {
      echo $ numero . 'es demasiado grande!' ;
   }
}
En este ejemplo, la calculadora clase de add () mĂ©todo muestra un comportamiento inesperado: se crea un AlertMechanism objeto y llama a uno de sus mĂ©todos. Este es un comportamiento inesperado y no deseado, los consumidores de la biblioteca nunca esperará un mensaje impreso en la pantalla. En cambio, sĂłlo esperan que la suma de los nĂşmeros proporcionados.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
clase Calculadora {
   privado $ primerNumero ;
   privado $ secondNumber ;
   funciĂłn __construct ( $ primerNumero , $ secondNumber ) {
      $ This - primerNumero> = $ primerNumero ;
      $ This -> secondNumber = $ secondNumber ;
   }
   funciĂłn add () {
      devolver $ this -> primerNumero + $ this -> secondNumber;
   }
   funciĂłn de resta () {
      devolver $ this - primerNumero> - $ this - secondNumber>;
   }
}
clase AlertMechanism {
   funciĂłn checkLimits ( $ primerNumero , $ secondNumber ) {
      $ Suma = ( nueva Calculadora ( $ primerNumero , $ secondNumber )) -> add ();
      si ( $ suma > 100) {
         $ This -> tooBigNumber ( $ cantidad );
      }
   }
   funciĂłn tooBigNumber ( $ numero ) {
      echo $ numero . 'es demasiado grande!' ;
   }
}
Esto es mejor. AlertMechanism no tiene efecto en Calculadora . En su lugar, AlertMechanism usa lo que necesita con el fin de determinar si una alerta debe ser emitido.

Dependencia y acoplamiento

En la mayoría de los casos, estas dos palabras son intercambiables, pero, en algunos casos, un término se prefiere sobre otro.
Entonces, ¿quĂ© es una dependencia ? Cuando el objeto A necesita usar objeto B , con el fin de realizar su comportamiento prescrito, se dice que A depende de B . En OOP, las dependencias son muy comunes.Objetos con frecuencia trabajan con y dependen unos de otros. AsĂ­, mientras que la eliminaciĂłn de la dependencia es una actividad noble, es casi imposible hacerlo. El control de las dependencias y la reducciĂłn de ellos es, sin embargo, preferible.
Los tĂ©rminos, pesado acoplamiento- y -suelta de acoplamiento , por lo general se refieren a la cantidad de un objeto depende de otros objetos.
En un sistema de acoplamiento flexible, los cambios en un objeto tienen un efecto reducido sobre los otros objetos que dependen de Ă©l. En tales sistemas, las clases depende de interfaces en lugar de implementaciones concretas (hablaremos más sobre esto más adelante). Por ello, los sistemas dĂ©bilmente acoplados son más abiertos a modificaciones.

Acoplamiento en un campo

Veamos un ejemplo:
1
2
3
4
5
6
clase Display {
   privado $ calculadora ;
   funciĂłn __construct () {
      $ This -> calculadora = nueva Calculadora (1,2);
   }
}
Es comĂşn ver este tipo de cĂłdigo. Una clase, la pantalla en este caso, depende de la calculadora declase por referencia directa a esa clase. En el cĂłdigo anterior, Display 's $ calculadora campo es de tipo calculadora . El objeto que contiene el campo es un resultado de llamar directamente Calculadoraconstructor 's.

Acoplamiento mediante el acceso a los métodos de la clase

Revise el cĂłdigo siguiente para una demostraciĂłn de este tipo de acoplamiento:
1
2
3
4
5
6
7
8
9
clase Display {
   privado $ calculadora ;
   funciĂłn __construct () {
      $ This -> calculadora = nueva Calculadora (1, 2);
   }
   funciĂłn printSum () {
      echo $ this -> Simulador-> add ();
   }
}
La visualizaciĂłn de la clase llama la Calculadora objeto add () mĂ©todo. Esta es otra forma de acoplamiento, ya que una clase accede a la del otro mĂ©todo.

Acoplamiento de Referencia de los métodos

Puedes par de clases con referencias a mĂ©todos, tambiĂ©n. Por ejemplo:
1
2
3
4
5
6
7
8
9
10
11
12
clase Display {
   privado $ calculadora ;
   funciĂłn __construct () {
      $ This -> calculadora = $ this -> makeCalculator ();
   }
   funciĂłn printSum () {
      echo $ this -> Simulador-> add ();
   }
   funciĂłn makeCalculator () {
      volver nueva Calculadora (1, 2);
   }
}
Es importante señalar que la makeCalculator () mĂ©todo devuelve una calculadora objeto. Esta es una dependencia.

Acoplamiento de polimorfismo

La herencia es probablemente la forma más fuerte de dependencia:
1
2
3
4
5
clase AdvancedCalculator extiende Calculadora {
   funciĂłn sinusal ( $ valor ) {
      volver pecado ( $ valor );
   }
}
No sĂłlo puede AdvancedCalculator no hacer su trabajo sin calculadora , sino que ni siquiera podrĂ­a existir sin ella.

Acoplamiento reductor de InyecciĂłn de Dependencia

Se puede reducir el acoplamiento mediante la inyecciĂłn de una dependencia. He aquĂ­ un ejemplo de ello:
1
2
3
4
5
6
7
clase Display {
   privado $ calculadora ;
   funciĂłn __construct (calculadora calculadora $ = null) {
      $ This -> calculadora = $ calculadora ? : $ this -> makeCalculator ();
   }
/ / ... / /
}
Mediante la inyecciĂłn de la calculadora de objeto a travĂ©s de la pantalla 's constructor, redujimosDisplay 's dependencia a la Calculadora de clase. Pero esto es sĂłlo la mitad de la soluciĂłn.

Acoplamiento reductor con interfaces

TambiĂ©n podemos reducir el acoplamiento mediante el uso de interfaces. Por ejemplo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
interfaz CanCompute {
   funcionar add ();
   funciĂłn de resta ();
}
clase Calculadora implementa CanCompute {
   privado $ primerNumero ;
   privado $ secondNumber ;
   funciĂłn __construct ( $ primerNumero , $ secondNumber ) {
      $ This - primerNumero> = $ primerNumero ;
      $ This -> secondNumber = $ secondNumber ;
   }
   funciĂłn add () {
      devolver $ this -> primerNumero + $ this -> secondNumber;
   }
   funciĂłn de resta () {
      devolver $ this - primerNumero> - $ this - secondNumber>;
   }
}
clase Display {
   privado $ calculadora ;
   funciĂłn __construct (CanCompute $ calculadora = null) {
      $ This -> calculadora = $ calculadora ? : $ this -> makeCalculator ();
   }
   funciĂłn printSum () {
      echo $ this -> Simulador-> add ();
   }
   funciĂłn makeCalculator () {
      volver nueva Calculadora (1, 2);
   }
}
Usted puede pensar en ISP como un principio de cohesiĂłn de nivel superior.
Este cĂłdigo se introduce el CanCompute interfaz. Una interfaz es tan abstracto como usted puede conseguir en programaciĂłn orientada a objetos, sino que define los miembros que una clase debe implementar. En el caso del ejemplo anterior, Calculadora implementa la CanComputeinterfaz.
Display constructor 's espera un objeto que implementaCanCompute . En este punto, la pantalla dependencia 's con calculadora está efectivamente roto. En cualquier momento, podemos crear otra clase que implementaCanCompute y pasar un objeto de esa clase de Pantallaconstructor 's. Display ahora sĂłlo depende de laCanCompute interfaz, pero incluso esa dependencia es opcional. Si no pasa argumentos a la pantalla constructor @ s, sino que simplemente va a crear un clásico Calculadora objeto llamando makeCalculator () . Esta tĂ©cnica se utiliza con frecuencia, y es extremadamente Ăştil para desarrollo basado en pruebas (TDD).

Los principios sĂłlidos

SOLID es un conjunto de principios para escribir cĂłdigo limpio, que a su vez hace que sea más fácil de cambiar, mantener y ampliar en el futuro. Son recomendaciones que, cuando se aplica a cĂłdigo fuente, tienen un efecto positivo sobre la capacidad de mantenimiento.

Un poco de historia

Los principios sĂłlidos, tambiĂ©n conocidos como principios ágiles, fueron definidos inicialmente por Robert C. Martin. A pesar de que Ă©l no ha inventado todos estos principios, Ă©l fue quien los puso juntos. Usted puede leer más sobre ellos en su libro: Agile Software Development, principios, patrones y prácticas .SĂłlidos principios cubren una amplia gama de temas, pero voy a presentarlos en una forma tan simple como que soy capaz. No dude en pedir detalles adicionales en los comentarios, si es necesario.

Principio de responsabilidad individual (SRP)

Una clase tiene una responsabilidad Ăşnica. Esto puede sonar simple, pero a veces puede ser difĂ­cil de entender y poner en práctica.
1
2
3
4
5
6
clase Reportero {
   funciĂłn generateIncomeReports ();
   funciĂłn generatePaymentsReports ();
   funciĂłn computeBalance ();
   funciĂłn PrintReport ();
}
¿QuiĂ©n crees que se beneficia de esta clase de comportamiento '? Bueno, un departamento de contabilidad es una opciĂłn (para el resto), el departamento de finanzas puede ser otra (para los informes de ingresos / pagos), e incluso el departamento de archivo puede imprimir y archivar los informes.
Hay cuatro razones por las que podría tener que cambiar esta clase; cada departamento pueden querer que sus respectivos métodos personalizados para sus necesidades.
La SRP recomienda romper esas clases en otras más pequeñas, beahvior clases especĂ­ficas, teniendo cada uno una sola razĂłn para cambiar. Tales clases tienden a ser altamente cohesiva y ligeramente acopladas. En un sentido, SRP es la cohesiĂłn se define desde el punto de vista de los usuarios.

Dependencia Principio InversiĂłn (DIP)

Este principio establece que altos mĂłdulos no debe depender de mĂłdulos de bajo nivel, ambos deben depender de abstracciones. Las abstracciones no deben depender de los detalles, los detalles deben depender de las abstracciones. En pocas palabras, usted debe depender de abstracciones tanto como sea posible y nunca en las implementaciones concretas.
El truco con el DIP es que se desea invertir la dependencia, pero quiere mantener el flujo de control.Vamos a revisar nuestro ejemplo de la OCP (los interruptores y Luz clases). En la implementaciĂłn original, que tenĂ­a un interruptor de controlar directamente una luz.
Como se puede ver, tanto la dependencia y el control de flujo de interruptor hacia la Luz . Si bien esto es lo que queremos, no queremos depender directamente de la Luz . AsĂ­ que hemos introducido una interfaz.
Es increĂ­ble cĂłmo la simple introducciĂłn de una interfaz que hace que nuestro cĂłdigo respeto tanto DIP y OCP. Como se puede ver, no, clase depende de la aplicaciĂłn concreta de la Luz , y tanto la luz yinterruptor depende de la Conmutable interfaz. Hemos invertido la dependencia, y el flujo de control se mantuvo sin cambios.

Diseño de Alto Nivel

Otro aspecto importante de su cĂłdigo es su alto nivel de diseño y arquitectura en general. Una arquitectura enredado que el cĂłdigo sea difĂ­cil de modificar. Mantener una arquitectura limpia es esencial, y el primer paso es comprender cĂłmo separar las diferentes preocupaciones de su cĂłdigo.
En esta imagen, he tratado de resumir las principales preocupaciones. En el centro del esquema es nuestra lĂłgica de negocio. Se debe estar bien aislado del resto del mundo, y ser capaz de trabajar y se comportan como se espera, sin la existencia de ninguna de las otras partes. VĂ©anlo como ortogonalidad en un nivel superior.
A partir de la derecha, usted tiene su "principal" - el punto de entrada a la aplicaciĂłn - y las fábricas que crean objetos. Una soluciĂłn ideal serĂ­a conseguir sus objetos de fábricas especializadas, pero que es sobre todo imposible o poco práctico. Sin embargo, usted debe utilizar las fábricas cuando se tiene la oportunidad de hacerlo, y mantenerlos fuera de la lĂłgica empresarial.
Luego, en la parte inferior (en naranja), tenemos la persistencia (bases de datos, accesos a ficheros, comunicaciones de red) para fines de informaciĂłn persistente. NingĂşn objeto de nuestra lĂłgica de negocios debe saber cĂłmo funciona persistencia.
A la izquierda es el mecanismo de entrega.
Un MVC, como Laravel o CakePHP, sólo debe ser el mecanismo de entrega, nada más.
Esto le permite intercambiar un mecanismo a otro sin tocar la lĂłgica empresarial. Esto puede sonar extraño para algunos de ustedes. Se nos dice que nuestra lĂłgica de negocios debe ser colocado en nuestros modelos. Bueno, estoy de acuerdo. Nuestros modelos deben ser "modelos de solicitud", es decir, objetos mudos de datos utilizados para pasar informaciĂłn de MVC a la lĂłgica de negocio. Opcionalmente, no veo ningĂşn problema incluyendo la validaciĂłn de entrada en los modelos, pero nada más. La lĂłgica de negocio no deben estar en los modelos.
Cuando nos fijamos en la arquitectura de la aplicaciĂłn o de la estructura de directorios, deberĂ­a ver una estructura que sugiere lo que el programa hace lo contrario de lo que marco o base de datos que utiliza.
Por Ăşltimo, asegĂşrese de que todas las dependencias punto hacia nuestra lĂłgica de negocio. Las interfaces de usuario, fábricas, bases de datos son aplicaciones muy concretas, y nunca debe depender de ellos. InversiĂłn de las dependencias para que apunten hacia nuestra lĂłgica de negocio modulariza nuestro sistema, lo que nos permite cambiar las dependencias sin modificar la lĂłgica de negocio.

sábado, 16 de febrero de 2013

Convierte tu dispositivo Android en un control remoto


Nuestros dispositivos mĂłviles nos permiten realizar multitud de cosas más allá de hablar por telĂ©fono; podemos intercambiar ficheros con nuestros amigos, subirlos a la nube, enviarnos correos electrĂłnicos o mensajes a travĂ©s de WhatsApp o Line, navegar por Internet o compartir nuestra ubicaciĂłn a travĂ©s de Foursquare. De hecho, con el extenso abanico de aplicaciones disponibles, podemos trabajar casi como si estuviĂ©semos en la oficina, editar vĂ­deos o realizar diseños en 3D.
control remoto - android
Otra de las posibilidades que nos ofrecen nuestros dispositivos mĂłviles es la posibilidad de convertirlos en controles remotos, es decir, conectarnos con ellos a nuestro ordenador (sin necesidad de tener que levantarnos del sofá o tener que ir a nuestra habitaciĂłn) o, incluso, usarlos como mando a distancia para controlar un pase de diapositivas o para controlar nuestra televisiĂłn, nuestro ordenador o nuestro media center.
En el caso de disponer de un dispositivo Android y una red Wi-Fi en casa, nuestro dispositivo mĂłvil, además de ofrecernos acceso a Internet, tambiĂ©n puede interactuar con nuestros televisores y demás dispositivos, incluso, controlar a distancia el reproductor multimedia de nuestro ordenador personal, unas funcionalidades para sibaritas de las que vamos a conocer algunas opciones:

Media Remote for Android

Media Remote for Android es una aplicaciĂłn Android que ha lanzado Sony para smartphones y para tabletascon la que podremos controlar, cĂłmodamente con nuestro dispositivo mĂłvil, los reproductores Blu-ray de Sony con conexiĂłn a nuestra LAN interna asĂ­ como una amplia gama de televisores de la serie Bravia, amplificadores de audio e, incluso, algĂşn modelo de ordenador de la serie VAIO.
La aplicaciĂłn, además del control remoto, nos ofrece un teclado completo para hacernos más sencillo navegar por Internet a travĂ©s de nuestro Smart TV, enviar URLs desde el dispositivo mĂłvil hasta el navegador de la televisiĂłn (un detalle más que interesante), ver la informaciĂłn del disco Blu-ray que tenemos en el reproductor o usar nuestra tableta o nuestro smartphone como mando de los juegos que soportan las Smart TVs de Sony.
Además de las aplicaciones para Android, Media Remote de Sony tambiĂ©n está disponible para iOS.

Yatse, the XBMC Remote

XBMC es un proyecto en software libre que nos ofrece un completo media center que podemos desplegar en equipos Linux (incluyendo Raspberry Pi), Windows o incluso en Mac; un software que convierte cualquier ordenador en un completo centro de entretenimiento con el que ver nuestra colecciĂłn de pelĂ­culas o acceder a contenidos a travĂ©s de Internet. Si bien podemos controlar XBMC con un teclado y un ratĂłn inalámbricos, nuestro smartphone tambiĂ©n puede actuar de control remoto y, en el caso de Android, Yatse es una de las mejores opciones disponibles.
Yatse XBMC remote
Con Yatse podremos acceder al catálogo de contenidos que tenemos en nuestro media center (pelĂ­culas, series de televisiĂłn, documentales, mĂşsica, etc), controlar XBMC a distancia desde nuestro smartphone o nuestra tableta, acceder a la informaciĂłn de los contenidos, desplegar un teclado sobre nuestro smartphone, elegir los subtĂ­tulos para los contenidos, lanzar nuestros playlists, etc

Ubuntu Remote Control

Ubuntu Remote Control es un control remoto para equipos que tienen instalado Ubuntu, es decir, podremos convertir nuestro smartphone o nuestra tableta en un mando a distancia con el que controlar nuestro ordenador con Ubuntu.
Ubuntu Remote
Aunque la instalaciĂłn a primera vista parece compleja, y requiere que el equipo tenga instalado un servidor SSH (openssh-server), con esta aplicaciĂłn Android podremos controlar el reproductor multimedia del ordenador (pasar a la siguiente canciĂłn, subir el volumen, etc), sacar una captura de la pantalla del PC y visualizarla desde Android, tomar el control de la webcam del equipo en remoto y tomar fotos, apagar o reiniciar el equipo, acceder a la consola o bloquear el equipo en remoto usando una cĂłmoda interfaz gráfica desde nuestra tableta o nuestro smartphone Android.

Samsung Remote

Samsung Remote es la aplicaciĂłn Android oficial de Samsung que convierte nuestro smartphone en un control remoto de las Smart TVs de este fabricante.
Podremos conectar nuestro smartphone Android tanto a travĂ©s de la red Wi-Fi de nuestra casa como a travĂ©s de la conexiĂłn Bluetooth si nuestro televisor lo soporta y, a partir de ahĂ­, podremos gestionar la televisiĂłn y el reproductor BluRay para lanzar aplicaciones, escribir cĂłmodamente (para no tener que usar el teclado por pantalla con el mando a distancia de la TV), cambiar de canal, subir el volumen y, básicamente, el mismo tipo de funciones que podrĂ­amos hacer con el mando convencional pero, eso sĂ­, de una manera mucho más cĂłmoda.
Por cierto, en iOS tambiĂ©n está disponible.

Remote para Grooveshark

Remote para Grooveshark es una aplicaciĂłn dedicada a los fanáticos de Grooveshark, el servicio destreaming de mĂşsica. Con esta aplicaciĂłn para Android podremos convertir nuestro smartphone o nuestra tableta en un control remoto de nuestro PC o Mac y gestionar, a distancia, la reproducciĂłn de canciones en Groooveshark tanto en Android como en iOS.
Remote for Grooveshark
La aplicaciĂłn no es un cliente para dispositivos mĂłviles sino que es un control remoto que funciona en conjunciĂłn con una extensiĂłn para FirefoxChrome o Safari y que tendremos que emparejar con nuestro dispositivo mĂłvil y nuestra cuenta de Grooveshark para gestionar la reproducciĂłn en remoto.

Framework Zend con Base de datos


el trabajo con bases de datos, el concepto de modelo dentro de MVC ¿QuĂ© es un modelo? , esta pregunta es bastante fácil de responder: el modelo es el que se encarga de la lĂłgica de negocio, de inserts, updates y deletes. En general, siempre que haya datos que procesar, se procesarán en el modelo.
Sin embargo no va a ser la primera ni la Ăşltima vez que surjan dudas al respecto, “que esto no va en el modelo”“que esto si va en el modelo”, etc. Sin embargo, me arriesgo a hacer una afirmaciĂłn que puede ser fácilmente criticada: todo proceso de datos va en el modelo. Hay una regla en inglĂ©s que dice “skinny controllers, fat models”.
Básicamente la idea de esto es que el controlador sólo funcione como intermediario entre la vista y el modelo cuando sea necesario, que no realice ninguna otra actividad, que toda la lógica este contenida en el modelo. De esta manera, lograremos tener nuestro código mucho más organizado y limpio.
Dentro de un sistema MVC, los modelos contienen la lĂłgica de negocio. Se encargan de la lectura/escritura de la informaciĂłn, asĂ­ que estaremos trabajando con ellos constantemente. El controlador puede comunicarse con los modelos para pedir y modificar datos, mientras que la vista puede leer datos pero no puede escribir.

Zend_Db_Select

Zend_Db_Select nos provee una API orientada a objetos para crear SQL SELECT’s, permitiĂ©ndonos setear individualmente cada parte del query. No es obligatorio usarlo en nuestros modelos. Si es una consulta simple podemos escribir el select normalmente, aunque en consultas más complejas que necesitamos ir armando por partes va a ser de gran ayuda.
La forma más fácil de crear un select object es con el método select() del db adapter:
$select = $dbAdapter->select();
Hecho esto, veamos rápidamente los métodos más usados:
// setear el from
$select->from("miTabla", "estaColumna");
// setear el from asignandole un alias a la tabla y especificando que campos queremos pedir
$select->from(array("esteAlias" => "estaTabla"), array("esteCampo", "yEsteOtro"));
->where("activo = 1"); // agrega un
// agrega una clausula AND al where $select->where("nombre = ?", $nombre); $selec ta clausula OR $select->orWhere("activo = 2"); $select->group("pais");
($count, $offset); $select->order("id DESC");
$select->joinLeft("otraTabla", "otraTabla.id = tabla.id"); $select->limi
t
Por Ăşltimo, haciendo echo $select; obtenemos la consulta SQL correspondiente.
Sin embargo, el 99% de las veces que queramos armar un select vamos a estar dentro de un modelo, así que obtenemos una instancia con el método select() de Zend_Db_Table_Abstract:
// en un modelo
$select = $this->select();
Este select no será un Zend_Db_Select, sino que será una versiĂłn especial llamadaZend_Db_Table_Select, sin embargo todos los mĂ©todos nombrados anteriormente funcionan, con un par de agregados. Por un lado, automáticamente setea el from() adecuado segĂşn la tabla del modelo actual, asĂ­ que ese paso podemos obviarlo. Por otro lado, por defecto no permite realizar joins a otras tablas, por lo que si lo hacemos obtendremos un error. Para evitar esto, al momento de hacer un join deberemos cambiar este comportamiento con el mĂ©todo setIntegrityCheck():
$select = $this->select()->setIntegrityCheck(false)->joinLeft(...);
y listo, problema solucionado!
Hecho este rápido repaso a Zend_Db_Select (los obligo a leer el manual para obtener algo más de info y ejemplos!) también hablaré un poco de Zend_Db_Expr:
Supongamos que hacemos esto:
$select->from($tabla, array("COUNT(*)", "nombre", "pais"));
a simple vista esta bien, pero cuando Zend arma el select se da cuenta que "COUNT(*)" no es un campo correspondiente a la tabla por lo que genera un error. Para este caso hacemos uso de Zend_Db_Expr:
$count = new Zend_Db_Expr("COUNT(*)");
$select->from($tabla, array($count, "nombre", "pais"));
Otra forma que tenemos de hacer esto mismo es escribiendo la expresión entre paréntesis, y Zend automáticamente lo convertirá a una Zend_Db_Expr:
$select->from($tabla, array("(COUNT(*))", "nombre", "pais"));
Como comentario final sobre el tema, cuando querramos usar un subquery en algĂşn select, deberemos pasarlo como una Zend_Db_Expr.

Zend_Db_Table

Implementando el patrón Table Data Gateway, Zend_Db_Table representa las diferentes tablas de nuestra bdd. Es decir que, por cada tabla sobre la que queramos trabajar, tendremos un modelo que extienda de Zend_Db_Table_Abstract. Como veremos más adelante nos brinda diferentes métodos para realizar INSERT's, UPDATE's, y demás operaciones.
Supongamos que tenemos nuestra tabla "mdw_usuarios", cuyo primary key es "id_usuario", nuestro modelo quedarĂ­a de la siguiente manera:
class Mdw_Model_Usuarios extends Zend_Db_Table_Abstract {
protected $_name = "mdw_usuarios";
} $usuarios = new Mdw_Model_Usuari
protected $_primary = "id_usuario"; os;</pre></div>
los atributos $_name y $_primary ya podemos trabajar sobre dicha tabla. Si no completamos $_primary, ZF tratará de buscarlo. Si la tabla no tiene una primary key, no puede ser usada con Zend_Db_Table.</p> <h3>Operaciones
<p>Especificando básicas</h3> <div class="codigo"><pre>$data = array("nombre" => $nombre, "apellido" => $apellido, "email" => $email);
$usuarios->insert($data);
Crear un insert es así de simple: simplemente le pasamos como parámetro un array cuyas claves son los nombres de los campos con su correspondiente valor.
Realizar un update es muy parecido solo que tenemos un segundo parámetro para especificar el where:
$data = array("email" => $nuevoEmail);
$where = "id_usuario = 2";
ere);</pre></div> <p>Por su parte para realiz
$usuarios->update($data, $w har un delete debemos especificar un where con los campos a eliminar:</p>
ere);
<div class="codigo"><pre>$where = "id_usuario = 3"; $usuarios->delete($w
h

Obteniendo datos de la bdd

Tenemos varias formas de leer datos de la bdd. La primera es con el método find(), que busca filas por su primary key, así que ese es el único parámetro que tenemos que enviar.
Por ejemplo para leer la fila correspondiente a id_usuario = 1:
$rows = $usuarios->find(1);</pre></div>
<p>También podemos obtener datos de más de un usuarios, enviando un array:</p>
<div class="codigo"><pre>// id_usuario = 1, 2, 3
v> <p>Find() devuelve un objeto del tipo Zend_Db_Tab
$rows = $usuarios->find(array(1, 2, 3));</pre></d
ile_Rowset_Abstract sobre el que podemos trabajar directamente, por ejemplo lo podemos recorrer con un foreach:</p>
<div class="codigo"><pre>foreach ($rows as $row) { echo $row->nombre . "<br />";
}
Si quisieramos también podríamos obtener los datos en un array php:
$arrayRows = $rows->toArray(); 
La segunda forma de leer informacion es con el metodo fetchAll($where, $order, $count, $offset). Ningun parámetro es obligatorio, es decir que haciendo $model->fetchAll() obtendremos todos los registros de esa tabla.
$model->fetchAll("id_pais = 3"); // todos los usuarios cuyo id_pais = 3
$model->fetchAll($select, "apellido ASC", 10); // 10 usuarios cuyo ud_pais = 3, ordenados por apellido, podemos pasar un Zend_Db_Select en el where
El fetchAll() también nos devuelve un rowset.

Zend_Db_Table_Rowset y Zend_Db_Table_Row

Un Row corresponde a una fila de la base de datos, y un Rowset es un conjunto de Rows, por lo tanto representa un conjunto de filas de la base de datos. Al hacer una consulta, tanto find() como fetchAll() devuelven un Rowset con los resultados obtenidos, y al recorrer ese Rowset cada elemento es un Row.
Anteriormente vimos que el Rowset lo podemos recorrer con un foreach, convertirlo en array, etc. En cuanto al Row veremos algunas cosas más. Suponiendo que tenemos una columna llamada "id_usuario", podremos acceder a su valor de la siguiente manera:
$row->id_usuario; 
Un Row implementa el patron Row Data Gateway, por lo que podemos crear, eliminar y actualizar datos directamente desde él:
$row->delete(); // elimina el registro de la bdd
$row->nombre_usuario = 'Pepe'; // modificamos el nombre de usuario
$row->save(); // y guardamos los cambios
$this->createRow(); $this->nom
// para crear un nuevo registro $newRow =bre = "Usuario nuevo"; $this->edad = 14;
$this->save();