Páginas

lunes, 1 de febrero de 2016

Diseñando una aplicación desde cero parte 2

Buen día, en la entrada anterior obtuvimos un diagrama de clases según un requerimiento ahora comenzaremos a convertir este diagrama en una app funcional, para esto podemos utilizar cualquiera de los frameworks de la variedad que tenemos en php (symfony, laravel, yii, zend, etc.) o incluso php puro y duro (para mi usar un framework opción super recomendada), en esta entrada se trabajará con symfony2.8 destacando que no es un tutorial de como trabajar con symfony por lo que no se explicará estructura del framework ni nada por el estilo, el punto es ir haciendo la aplicación según el diseño, el mismo diseño debería de servir para cualquier otro y ya con las manos en el código se mostrará como ir aplicando Test Development driver TDD a nuestra aplicación, por supuesto usando PHPUnit como framework base paras las pruebas unitarias.

Lo primero es conocer un poco de TDD, en síntesis la teoría es la siguiente, escribe la test de la funcionalidad a aplicar, corre el test y estarás en rojo, realiza el código para que la test funcione y pasa a verde, el punto principal es que según el diseño que se pensó para la aplicación se vayan realizando las test y codeando la funcionalidad, no es hacer un millón de test y luego ir al código sino al contrario, escribe test, escribe el condigo necesario de la funcionalidad para que ella pase a verde y pasa a la siguiente test, repite hasta que termines la app (suena divertido :)). Aplica refactory si es necesario (no es el tema principal en este artículo pero es parte del ciclo de TDD), ahora sí manos al código.

Según el diagrama diseñado en la entrada anterior tenemos una entidad Album y una Artista por lo que lo primero que tenemos que hacer son comenzar las test de nuestra entidad, para ello en la carpeta de test escribimos lo siguiente


https://gist.github.com/carlosbelisario/71c1ba6b81ce22943a5b

Como podemos ver, la test es simple y se autocomenta (importante para las test ya que las mismas no sirven de doc muchas veces) y lo que probamos es que haya instancia de nuestra entity a testear. Una vez culminado el código de la test procedemos a correrlo lo cual nos dará como resultado

.PHP Fatal error:  Class 'AppBundle\Entity\Album' not found ...


Es lo esperado según la técnica que estamos usando, el test esta en rojo ¿por que? obviamente no hemos aún creado nuestra entidad, en el caso de symfony podemos hacer uso de su consola para crearla o podemos hacerlo a pie (a gusto del consumidor) y obtendremos

https://gist.github.com/carlosbelisario/714a37a94c6c0258b64d

si volvemos a correr nuestra test ahora si tendremos el verde que deseamos y si ya finalizamos la primera test, simple cierto.

Seguimos revisando nuestro diseño y vemos que nuestra entidad tiene comportamiento que debemos testear, si tenemos un método para añadir los artistas a nuestro album y según la cardinalidad podemos agregar muchos artistas al mismo, doctrine nos provee de un tipo de datos llamado ArrayCollection que implementaremos en la entidad, pero vayamos a la test

https://gist.github.com/carlosbelisario/790574b289899627a5e7

Como se puede observar, la test cambio un poco añadimos un método setUp para inicializar en cada test nuestro objeto a testear Album en este caso, y se añadió la funcionalidad que se necesita si volvemos a correr la test encontraremos que estamos en rojo nuevamente y ¿que tenemos que hacer? realizar el código para pasar a verde, el cual para nuestro caso será el siguiente.

https://gist.github.com/carlosbelisario/283f67b5adeb06168937

Volvemos a correr la test y ya nuevamente todo en verde, en este punto podemos ver que tenemos setter y getter dentro de nuestra entidad (el comando de consola de doctrine es genial y nos creo todos los que necesitamos) la pregunta del millon

¿se deben hacer test de todos los getter y setter?

En mi opinión personal no, solo si tienen alguna lógica específica se deberían de hacer test, documentandome sobre el tema he leído personas que concuerdan con este punto, pero todo es cuestión de puntos de vistas y opiniones

Como podemos ver ya hemos implementado las test de la primera entidad (el comando de consola de doctrine nos apoyo con el segundo método que faltaba) el cual podemos ver su test aquí

https://gist.github.com/carlosbelisario/770c537ca6802cb6c80b

Antes de concluir es importante indicar que una test en rojo no significa que sea un error y una test en verde no significa que la test este 100% correcta siempre hay que tener en cuenta el concepto de refactory para nuestras test y nuestro código de manera que el software que tengamos sea software de calidad.

Espero que la entrada sea de agrado cualquier comentario o mejora será bien recibido y recordar hay que crear test verlas en rojo y luego pasar a verde. Saludos

martes, 26 de enero de 2016

Curso de introducción a java challenge2

Buen día, en esta segunda entrada de los challenge que van saliendo del curso de lynda up and run java, ya con un poco más de contenido dado en el curso, ya indicaron la existencia de métodos, estructuras de control (bucles y condicionales), métodos y sobrecarga de métodos para jugar un poco más con lo que se puede hacer con lo dado y veamos que se puede hacer con el challenge al oopstyle

El reto en este caso no es más que llevar el costo de la estadía de los pacientes en un hospital, teniendo los siguientes datos

  1. datos de estadía
  2. hay que determinar si existen sobrecargos en la estadía
  3. cargos por medicamentos
  4. cargos por laboratorio
acá lo que se implemento del código


cualquier comentario, sugerencia critica es aceptada, saludos

lunes, 25 de enero de 2016

Challenge1 curso up and run java lynda

Buen día, en esta entrada estaré compartiendo un repositorio que he creado para los challege del curso de java que estoy realizando en lynda.com, el punto principal es mostrar el código de estos challenge como los va brindando el instructor de lynda, cabe destacar que es un curso introductorio a java, el primer challenge como no se ha llegado a la separación en objetos la gente de lynda lo hizo a la manera estructurada todo en el método main, pero por ir un poco más allá cree un paquete donde separe en objetos e hice el mismo programa al estilo POO.

El challenge trata acerca de calcular el área de pintura de una casa, quitando las ventanas y las puertas de la misma, la formula fue dada en el mismo curso, sin mas preambulo les dejo el repositorio con el código

Repositorio del Challenge1


Cabe destacar que no soy un experto en java, si consiguen detalles o piensan que hay una mejor manera de aplicar al código pueden dejarla en los comentarios serán bien recibidos, saludos y espero sea de su agrado

sábado, 23 de enero de 2016

Diseñando una aplicación desde un requerimiento (parte 1)

Buen día esta es la primera de varias entradas donde se diseñará y construirá una app partiendo desde un requerimiento, el mismo será el siguiente:
Se necesita una aplicación que permitirá a los gestores de una discográfica mantener su histórico de producciones, con la lista de los artistas que han participado en cada una. En particular, los usuarios deben poder:
1. Crear, modificar, borrar y listar (con todos los campos relacionados) álbumes
2. Crear, modificar, borrar y listar artistas
3. Añadir y quitar artistas de un álbum existente.
Notas adicionales:
• Un álbum tiene un título y una fecha de publicación.
• De los artistas se conoce el nombre y el instrumento o rol.
• Los artistas se presentarán en el orden en que han sido añadidos al álbum.
• La aplicación se ejecutará en un servidor accesible solo desde la oficina del promotor, y por lo tanto no necesita ningún tipo de control de acceso.
La idea principal es utilizar aplicar y compartir diferentes técnicas que utilizamos para el diseño y desarrollo de  una aplicación, sin más preámbulo comencemos con la primera fase (ya teniendo los requerimientos de la aplicación) la misma en nuestro caso será la identificación de entidades que participan dentro del sistema, viendo el requerimiento escrito buscaremos los sustantivos para hacer esta identificación, los cuales viendo el escrito muy simplemente se puede ver que estarán:

entities

Una vez identificadas las entidades pasamos a ver los atributos de las mismas de manera que podamos ir modelando la aplicación de manera correcta, los atributos los identificaremos en nuestros requerimientos como las características que describen a nuestras entidades, por lo que actualizando el diagrama de clases quedaría de la siguiente manera

entities-properties

Luego de tener las entidades con atributos pasaremos a verificar cuales serán las operaciones o métodos de las mismas, los métodos los reconoceremos por medio de verbos o acciones que según los requerimientos ejecutan las entidades, por lo que nuevamente actualizaremos el diagrama de clases el cual quedaría:

entities-operations

Ya tenemos nuestra primera instancia del diagrama de clases según lo descrito en el documento, una vez teniendo esto hacemos una revisión para ver que todo este correcto y de no ser así realizaremos un reactory para que el diseño quede acorde a lo que se pide en el requerimiento, entonces manos al diagrama.

Lo primero viendo los atributos de la clase Artista se puede observar que tenemos el atributo rol de tipo string (no lo especificaron pero es lo primero que se ocurre por la descripción de especifican del mismo, muy obviamente se nota que rol es una asociación a un artista por lo que tendremos que sacar una entidad de este tipo, agregaremos también el método para añadir y eliminar el rol a la asociación, también realizaremos la asociación de Album hacia Artista ya que en el requerimiento se nos indica que al Album se le añaden los artistas asociados al mismo, lo siguiente es que las acciones "Crear, modificar, borrar y listar" son lo que normalmente llamamos CRUD y serán realizadas por medio de un ORM que utilicemos (en siguiente entrada indicaremos cual en específico se utilizará) por lo que las sacaré a una entidad aparte que llamaré ORM, la misma tendrá las operaciones del CRUD, entonces nuestro diagrama de clase va quedando de la siguiente manera.


entities-refactory

Como podemos ver tenemos ya el diseño de lo que según el requerimiento de la aplicación necesitamos, si en algún momento se ve que se necesita algo más o hacer una modificación se realiza la refactorización del diagrama, aunque en general el mismo esta completo. Cualquier observación, sugerencia o modificación al diseño es bien recibida y/o debatida, saludos espero que la entrada sea de su interés y podamos debatir un poco sobre el proceso que se realizó

lunes, 3 de diciembre de 2012

Zend y Symfomy el equipo perfecto

Una diapositiva muy interesante que conseguí leyendo un poco los temas que se trataron en la ZendCon 2012 Espero que sirva un poco, para ver las cosas que se pueden hacer si se siguen bien los standares, saludos

miércoles, 8 de agosto de 2012

Script de comparación entre rangos de fechas

Este es un pequeño script que realice para dar una respuesta en foros del web, y me pareció que vale la pena compartirlo, ando un poco fiebruo con eso de los closures, por lo que me hice uno para hacer este script


date_default_timezone_set('UTC');

$rangeBettweenRange = function(array $range1, array $range2) {
    $from1 = new DateTime($range1[0]);
    $to1 = new DateTime($range1[1]);
    $from2 = new DateTime($range2[0]);
    $to2 = new DateTime($range2[1]);    

    $range1Diff = $from1->diff($to1);    

    for($i = 0; $i <= $range1Diff->days; $i++) {    
        if($from1 >= $from2 && $from1 <= $to2) {
            $return[$from1->format('d-m-Y')] =  "in the range 
";
        } else {
            $return[$from1->format('d-m-Y')] = "out the range
";
        }
        $from1->modify("+1 day");        
    }
    return $return;
};

El resultado es algo como esto
Array
(
    [01-01-2012] => out the range

    [02-01-2012] => out the range

    [03-01-2012] => out the range

    [04-01-2012] => out the range

    [05-01-2012] => out the range

    [06-01-2012] => out the range

    [07-01-2012] => out the range

    [08-01-2012] => out the range

    [09-01-2012] => out the range

    [10-01-2012] => out the range

    [11-01-2012] => out the range

    [12-01-2012] => out the range

    [13-01-2012] => out the range

    [14-01-2012] => out the range

    [15-01-2012] => in the range 

    [16-01-2012] => in the range 

    [17-01-2012] => in the range 

    [18-01-2012] => in the range 

    [19-01-2012] => in the range 

    [20-01-2012] => in the range 

    [21-01-2012] => in the range 

    [22-01-2012] => in the range 

    [23-01-2012] => in the range 

    [24-01-2012] => in the range 

    [25-01-2012] => in the range 

    [26-01-2012] => in the range 

    [27-01-2012] => in the range 

    [28-01-2012] => in the range 

    [29-01-2012] => in the range 

    [30-01-2012] => in the range 

    [31-01-2012] => in the range 

)
el que hacer con el resultado ya queda del desarrollador. Espero que el script sea de utilidad, saludos

jueves, 26 de julio de 2012

Temas más vistos y con más respuestas de MyBB Forum con YiiFramework

En esta entrada compartiré unos pequeños script que realice para la gente de yiiframework en español, esarriba, como hacerlo, luego en un proyecto creado con YiiFramework generamos el modelo Threads con la herramienta Gii de YiiFramework, también necesitaremos generar el modelo Posts,  un simple script que nos permite por medio de YiiFramework conocer los temas más vistos y con más respuestas de un foro de MyBB.

Aclarando que ya tenemos que tener configurado el foro de MyBB, pueden ver en el enlace que se dejo

arriba como hacerlo, luego en un proyecto creado con YiiFramework generamos el modelo Threads con la herramienta Gii de YiiFramework, también necesitaremos generar el modelo Posts ambos extienden del Active Record de Yii, comenzamos a trabajar en nuestro código








Lo primero es hacer la relación entre ambos models/Threads.php
    /**
     * @return array relational rules.
     */
     public function relations()
     {
        // NOTE: you may need to adjust the relation name and the related
 // class name for the relations automatically generated below.
 return array(
     'posts' => array(self::HAS_MANY, 'posts', 'tid'),
 );
     }
models/Posts.php
    /**
     * @return array relational rules.
     */
     public function relations()
     {
        // NOTE: you may need to adjust the relation name and the related
 // class name for the relations automatically generated below.
 return array(
            'threads' => array(self::BELONGS_TO, 'Threads', 'tid'),     
 );
     }

De esta manera tenemos la relación, una vez establecemos esto, realizamos el método hotpost, que es el que nos da los datos que necesitamos

/**
* hotThread return the hot threads of the foro
* @param  string  $type   [description]
* @param  integer $length [description]
* @return [type]          [description]
*/
public function hotThread($type = 'views', $length = 5)
{
    if($type == 'views') { //shows the hotpost for views
        $criteria = new CDbCriteria();
 $criteria->select = 'tid, subject, views, dateline, username';
 $criteria->with = array(
     'posts'=>array(                     
         'joinType'=>'LEFT JOIN', 
         'order' => 'pid',                     
         ),
 );   
 $criteria->order = 'views DESC';
 $criteria->together = true;   
 $criteria->limit = $length;
        $dataProvider = new CActiveDataProvider($this, array(
            'criteria' => $criteria,                                    
            'pagination'=>array(
                'pageSize'=>20,
            ),
        ));            
    } elseif($type == 'answerd') { //show the hotpost by answerd
        $criteria = new CDbCriteria();
 $criteria->select = 'tid, COUNT(posts.tid) as length, subject, views, dateline, username';   
 $criteria->order = 'length DESC'; 
 $criteria->with = array(
     'posts'=>array(                    
         'joinType'=>'RIGHT JOIN',  
         'order' => 'pid',         
         ),
 );
 $criteria->together = true;   
 $criteria->group = 'posts.tid';
 $criteria->limit = $length;
        $dataProvider = new CActiveDataProvider($this, array(
            'criteria' => $criteria,                                                    
        ));
    }
    return $dataProvider;
}

Como vemos estamos obteniendo un nuevo atributo para la categoría por respuesta, entonces tenemos que agregar a nuestra clase Threads el atributo length


class Threads extends CActiveRecord
{
    public $length;
    /*...*/   
Ya que obtuvimos los hotpost por su respectiva categoria (visitas y respuestas), ahora realizaremos el controller, controllers/SiteController.php
public function actionHotpost()
{        
    $threads = new Threads();  
    $dataProviderVisitPost = $threads->hotThread('views');
    $dataProviderMostAnswerdPost = $threads->hotThread('answerd');
    $this->render('index-test',array(
        'dataProviderVisitPost'=>$dataProviderVisitPost,
        'dataProviderMostAnswerdPost' => $dataProviderMostAnswerdPost)
    );                
}

Ahora, hacemos la vista, esta consta de un CListView,
views/site/index-test.php


pageTitle=Yii::app()->name; ?>

h1="">
titulo de la pagina
/h1>
h2="">
Temas más Visitados
widget('zii.widgets.CListView', array(
    'dataProvider'=>$dataProviderVisitPost,
    'itemView'=>'_hotpostitem', 
));?>

h2="">
Con mayor numero de respuesta /h2>
widget('zii.widgets.CListView', array(
    'dataProvider'=>$dataProviderMostAnswerdPost,
    'itemView'=>'_hotpostitemvisit',   
));?>

Disculpen los horrores en las etiquetas html, no le tengo instalado plugin para codigo al blog, por eso no esta el principio <.

Ahora solo nos queda realizar el código de
views/site/_hotpostitem.php


div class="view">     
   h2>subject); ?>/h2>
   span>Creado por: username);?> en la fecha dateline));?>/span>
   p>Visto: views); ?>/p>  
   p>posts[0]->message, 0, 350)); ?>/p>   
   a href="http://localhost/mybb/Upload/showthread.php?tid=tid)?>" alt="leer mas">Leer mas/a>
/div>
Y de views/site/_hotpostitemvisit.php
div class="view">     
   h2>subject); ?>/h2>
   span>Creado por: username);?> en la fecha dateline));?>/span>
   p>Cantidad de Respuestas: length - 1); ?>/p>  
   p>posts[0]->message, 0, 350)); ?>/p>   
   a href="http://localhost/mybb/Upload/showthread.php?tid=tid)?>" alt="leer mas">Leer mas/a>
/div>
Espero que este sirva de agrado a los que lo lean, el código pronto estará en github, en la cuenta de yienespanol y en la de mi persona, saludos