<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>error</title><link>https://devtia.com/</link><description>Llevamos empresas a la nueva era digital. Te ayudamos a mejorar tus procesos a través de las métricas.</description><language>es</language><pubDate>Thu, 30 Apr 2026 11:08:26 +0200</pubDate><lastBuildDate>Thu, 30 Apr 2026 11:08:26 +0200</lastBuildDate><generator>DEVTIA</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><ttl>3600</ttl><item><title>Nuestra garantía</title><link>https://devtia.com/post/nuestra-garantia</link><description><![CDATA[<p><strong>Ofrecer una buena garant&iacute;a </strong>en nuestro productos, el cual se convertir&aacute; en una importante pieza para la empresa que nos contrat&oacute; y que, probablemente acabar&aacute; siendo el eje central de numerosos procesos internos y externos, se hace <strong>vital para ofrecer una confianza extra a nuestros clientes</strong>.</p><p>Nuestra m&aacute;xima es ofrecer el mejor producto posible a un precio m&aacute;s que razonable. Para que el proyecto triunfe, tal y como explicamos en nuestra metodolog&iacute;a de trabajo, necesitaremos la mayor implicaci&oacute;n por parte del cliente en el proceso que acompa&ntilde;a al desarrollo del software.</p><p><strong>Nuestra garant&iacute;a es un fiel reflejo de esta implicaci&oacute;n exigida al cliente.</strong></p><div class="row mt-5"><div class="col-sm-3 pt-3"><img alt="Seguridad - Devtia" loading="lazy" src="/cache/thumb_1200_0800/uploads/content/image/image/e3443d8c4d4bdeb8c1a4288237a602571040177b.png" title="Seguridad - Devtia"></div><div class="col-sm-9"><h2 class="mt-0">INCLUIDO</h2><p>Nuestra garant&iacute;a incluye la <strong>correcci&oacute;n de todos aquellos defectos que puedan detectarse</strong> dentro del plazo incluido en la garant&iacute;a.</p><p>Nuestra garant&iacute;a cubre solamente los errores, no incluye modificaciones procesos a los que el cliente deber&iacute;a de haber prestado una atenci&oacute;n mayor y que no son derivados de nuestra actividad.</p></div><div class="row mt-0"><div class="col-sm-9 mt-5"><h2 class="mt-0">NO INCLUIDO</h2><p>Tampoco incluye <strong>modificaciones de textos ni nuevos requisitos o necesidades</strong> que aparecen despu&eacute;s de la entrega.</p></div><div class="col-sm-3 pt-3"><p><img alt="modificaciones de textos" loading="lazy" src="/cache/thumb_1200_0800/uploads/content/image/image/a8108be4ab65338c49f90c19111a48bbc1f7a7c4.png" title="Errores"></p></div></div><div class="row pt-3"><div class="col-sm-3 pt-5"><p><img alt="garant&iacute;a de correcci&oacute;n" class="d-none d-sm-block" loading="lazy" src="/cache/thumb_1200_0800/uploads/content/image/image/7eff5c351ed56de568ff636fe3df57d9430ba04f.png" title="garant&iacute;a de correcci&oacute;n"></p></div><div class="col-sm-9 pt-3"><h2 class="mt-0">DURACI&Oacute;N</h2><p>La garant&iacute;a ofrecida por DEVTIA es bastante simple, <strong>ofrecemos una garant&iacute;a de correcci&oacute;n de errores de tres meses en todos nuestros proyectos</strong> que comenzar&aacute; a contar tras la finalizaci&oacute;n del mismo. El cliente debe comprometerse a revisar en profundidad el funcionamiento de su proyecto en este plazo.</p><p>En caso de que por cualquier motivo, el cliente no pueda realizar estas comprobaciones para recurrir a la garant&iacute;a, no pasar&aacute; nada, no hay ning&uacute;n problema, <strong>queremos que nuestro producto funcione a la perfecci&oacute;n y vamos a encargarnos de reparar lo que debamos</strong>. Eso s&iacute;, en caso de recurrir a la garant&iacute;a fuera de plazo, el cliente tendr&aacute; que pagar por el tiempo adicional que dedicaremos a su proyecto.</p><p>Nuestra recomendaci&oacute;n es que, en la medida de lo posible, exprimas al m&aacute;ximo el funcionamiento de la herramienta durante estos tres meses para que no se escape ning&uacute;n posible error y no tengas que pagar ni un euro de m&aacute;s.</p></div></div></div>
]]></description><guid>https://devtia.com/post/nuestra-garantia</guid><pubDate>Tue, 28 Apr 2020 12:24:48 +0200</pubDate></item><item><title>Nuestros valores</title><link>https://devtia.com/post/nuestros-valores</link><description><![CDATA[<p><strong>Queremos construir un c&iacute;rculo de confianza</strong>, esta es nuestra forma de colaborar con nuestros empleados, proveedores y clientes.</p><div class="row"><div class="col-sm-8"><h2>Valores corporativos</h2><p>DEVTIA nace del conocimiento y expertise adquiridos en grandes corporaciones de desarrollo de software, con el prop&oacute;sito de mejorar los procesos y metodolog&iacute;a aplicados a la hora de afrontar proyectos de desarrollo a medida. Por esta raz&oacute;n <strong>nuestros valores son los cimientos de nuestra cultura corporativa</strong>. Si decides colaborar con nosotros, m&aacute;s all&aacute; de contratos y presupuestos puedes contar con la garant&iacute;a de que vamos a basar nuestra relaci&oacute;n en estos criterios. Nuestro objetivo es alcanzar la excelencia en estos valores que proponemos.</p><h2>Objetivo</h2><p>&iquest;Para que unos valores corporativos? En DEVTIA nos hemos propuesto el objetivo de <strong>establecer relaciones a largo plazo.</strong> Estos valores corporativos nos van a permitir este tipo de relaciones estables <strong>basadas en la confianza mutua</strong>.</p></div><div class="col-sm-4 d-none d-sm-block mt-5"><p><img alt="Nuestros valores corporativos son la transparencia y el compromiso" loading="lazy" src="/uploads/content/image/image/740480b48020c2a1c3bce22ef2699c33e6a11d7f.gif" title="Nuestros valores corporativos son la transparencia y el compromiso"></p></div></div><p>Nuestros valores te interesan si est&aacute;s pensando en trabajar con nosotros, da igual si vas a ser un empleado, un proveedor o un cliente, ya que estos valores aplican exactamente igual a todas las partes interesadas. <strong>Queremos construir un c&iacute;rculo de confianza</strong>, y dentro de este c&iacute;rculo de confianza esperamos que t&uacute; tambi&eacute;n tengas unos altos est&aacute;ndares, y que estos sean 100% compatibles con los nuestros.</p><h2>Transparencia y honestidad</h2><p>La transparencia es la capacidad de transmitir la realidad tal cual es. Muchas personas creen que su interlocutor quiere escuchar s&iacute; a todo. <em>El cliente siempre tiene la raz&oacute;n. </em><strong>En nuestra opini&oacute;n lo que realmente quiere escuchar es la verdad</strong>. La confianza se consigue a trav&eacute;s de una relaci&oacute;n de <strong>comunicaci&oacute;n honesta y fluida</strong>. Por esto nos esforzamos mucho en engrasar nuestros canales de comunicaci&oacute;n.</p><hr><div class="row "><div class="col-sm-3 reference"><p>Valoramos altamente la responsabilidad, por lo que nos tomamos muy en serio nuestro trabajo</p></div><div class="col-sm-9"><h2>Responsabilidad y compromiso</h2><p>La responsabilidad es la habilidad de poner todos los medios disponibles para la consecuci&oacute;n de un objetivo, dar cumplimiento a las obligaciones y ser cuidadoso en la toma de decisiones. Nosotros <strong>valoramos altamente la responsabilidad, por lo que nos tomamos muy en serio nuestro trabajo</strong>.</p><p>Obviamente nadie puede prometer resultados, el desarrollo de software es una tarea muy compleja en la que es habitual fallar tanto en las estimaciones como en cometer errores. Por eso nosotros hemos desarrollado una metodolog&iacute;a de trabajo que nos permite asegurar la calidad de nuestro trabajo de una forma realista y alcanzable.</p></div></div><hr><h2>Resumen</h2><p>La confianza es algo dif&iacute;cil de alcanzar en todos los &aacute;mbitos de la vida, y en especial en el &aacute;mbito laboral. <strong>Se pueden tardar meses e incluso a&ntilde;os forjar una relaci&oacute;n fuerte y perdurable en el tiempo</strong>. En DEVTIA cuidamos las relaciones como un aspecto de capital para la compa&ntilde;&iacute;a.</p>
]]></description><guid>https://devtia.com/post/nuestros-valores</guid><pubDate>Tue, 21 Jan 2020 22:38:00 +0100</pubDate></item><item><title>Programador pragmático: el gato se ha comido mi código</title><link>https://devtia.com/post/programador-pragmatico-el-gato-se-ha-comido-mi-codigo</link><description><![CDATA[<p><em>Photo by Anel Rossouw from Pexel</em></p><p>Este es el primero de una serie de entradas en las que analizamos el libro <a href="https://amzn.to/31e9I8v">pragmatic programmer</a> from journeyman to master publicado en el a&ntilde;o 1999 por Andrew Hunt y David Thomas. Puedes leer la serie en cualquier orden, o leer solamente las entradas que te interesen ya que son independientes entre s&iacute;.</p><p>Si te interesa, tambi&eacute;n puedes ver esta entrada en nuestro <a href="https://youtu.be/mVbbZI6U-EY">canal de youtube</a>.</p><p>Una de las ideas que subyacen en todo el libro <strong>es la responsabilidad</strong>. Responsabilidad de tus acciones, de tu carrera, de los proyectos en los que trabajas. Es cierto que <strong>muchas cosas no dependen de t&iacute;, pero si depende de t&iacute; la actitud que tomas cuando te enfrentas a ellas</strong>.</p><p>En esta l&iacute;nea de pensamiento no debes tener miedo a reconocer que no sabes algo, y sobre todo no debes tener miedo a reconocer que te has equivocado. Si te dedicas al mundo del desarrollo de software puedes estar seguro que ambas situaciones se van a dar antes o despu&eacute;s.</p><p>Lo importante es c&oacute;mo te enfrentas a estas situaci&oacute;nes. Aunque no lo creas, cuando has metido la pata, tambi&eacute;n es un buen momento para demostrar que eres un gran profesional.</p><p>Podemos estar orgullosos de las habilidades que tenemos, pero tambi&eacute;n podemos estar orgullosos de c&oacute;mo manejamos la situaci&oacute;n cuando nos equivocamos.</p><h2>&iquest;Cual es la forma correcta de actuar?</h2><ol><li>S&eacute; honesto y directo.</li><li>Avisa lo antes posible.</li><li>Nadie quiere saber cuales son tus excusas.</li><li>Ahora no importa quien es el culpable, tampoco importa lo que no puede hacerse.</li><li>Lo &uacute;nico que importa es que puede hacerse para paliar los da&ntilde;os y para volver a una situaci&oacute;n normal lo antes posible.</li></ol><h2>Analizar qu&eacute; ha ocurrido</h2><p>Una vez que la situaci&oacute;n de crisis ha pasado, ahora toca analizar que es lo que pas&oacute;.</p><ol><li>Sigue sin ser importante de quien fue la culpa, probablemente varias personas tienen una parte de culpa.</li><li>Importa que es lo que puedes hacer t&uacute; para que no vuelva a pasar.</li></ol><p>Apuntat&eacute; a nuestra academia si quieres recibir un consejo como este cada semana en tu bandeja de entrada.</p>
]]></description><guid>https://devtia.com/post/programador-pragmatico-el-gato-se-ha-comido-mi-codigo</guid><pubDate>Sun, 18 Oct 2020 15:52:42 +0200</pubDate></item><item><title>Código limpio: Pruebas automáticas</title><link>https://devtia.com/post/codigo-limpio-pruebas-automaticas</link><description><![CDATA[<p>En la &uacute;ltima entrada repasamos qu&eacute; deber&iacute;as tener en cuenta a la hora de realizar una correcta <a href="/post/codigo-limpio-gestion-de-errores">gesti&oacute;n de errores</a>. En esta entrada vamos a realizar una peque&ntilde;a intruducci&oacute;n a las pruebas autom&aacute;ticas, &iquest;qu&eacute; son? &iquest;para qu&eacute; sirven? y sobre todo que caracter&iacute;siticas tienen que tener para ser realmente &uacute;tiles.</p><h2>&iquest;Pruebas autom&aacute;ticas?</h2><p>Las pruebas o la bater&iacute;a de pruebas es un software que debe escribirse en paralelo a nuestro propio software y cuya responsabilidad es comprobar que nuestro software funciona correctamente. B&aacute;sicamente es <strong>software que prueba nuestro software</strong>.</p><p>Puede que intuitivamente pienses que construir una bater&iacute;a de pruebas, es trabajo adicional, ya que probablemente tardar&aacute;s m&aacute;s tiempo y por lo tanto tu trabajo ser&aacute; m&aacute;s caro para tus clientes pero esto no es as&iacute;.</p><p>Cuando tienes una buena bater&iacute;a de pruebas, la primera "derivada" es que vas a cometer menos errores. Menos errores supone menos tiempo arreglando errores y m&aacute;s tiempo programando. Adem&aacute;s supone menos frustraci&oacute;n en los usuarios.</p><p>La segunda derivada es que puedes hacer cambios con mayor confianza, y esto te hace ir m&aacute;s r&aacute;pido. Las pruebas detectar&aacute;n que has roto, y simplemente tendr&aacute;s que arreglarlo, un equipo con una buena bater&iacute;a de pruebas termina trabajando mucho m&aacute;s r&aacute;pido que un equipo que no las tiene.</p><p>Hay una tercera derivada y es que al desarrollar tu bater&iacute;a de pruebas te va a permitir dise&ntilde;ar mejor software, pero esto es algo en lo que profundizaremos en una entrada m&aacute;s adelante.</p><h2>&iquest;Si es tan bonito por que no todo el mundo hace pruebas autom&aacute;ticas?</h2><p>Cuando escribes pruebas debes ser tan cuidadoso c&oacute;mo con el c&oacute;digo de producci&oacute;n. Todo lo que hemos comentado ya en esta serie sobre elegir buenos <a href="/post/codigo-limpio-nombres">nombres</a>, <a href="/post/codigo-limpio-funciones">funciones</a>, <a href="/post/codigo-limpio-argumentos">argumentos</a>, etc son cosas que tambi&eacute;n aplican a las pruebas autom&aacute;ticas.</p><p>Escribir buenas pruebas requiere cierta t&eacute;cnica y ocurre que muchos programadores o equipos comienzan haciendo pruebas, y al no ser pruebas de calidad terminan teniendo una bater&iacute;a de pruebas que supone m&aacute;s un problema que una soluci&oacute;n. Tras esta mala experiencia desisten, por eso en esta entrada vamos a explicarte c&oacute;mo escribir buenas pruebas.</p><h2>Escribe tus pruebas "PRIMERO"</h2><p><img alt="Escribe pruebas r&aacute;pido" loading="lazy" src="/cache/thumb_1200_0400/uploads/content/image/image/dcc63077554f52edf72fcc4d5c15300636e851dc.jpg" title="Escribe pruebas r&aacute;pido"></p><p><em>FIRST</em> o PRIMERO es un acr&oacute;nimo que se utiliza para describir las caracter&iacute;sticas que deber&iacute;a tener una prueba.</p><h3><em>Fast</em> o R&aacute;pidas</h3><p>Una prueba, as&iacute; como la bater&iacute;a de pruebas a la que pertenecen deber&iacute;an ser tan r&aacute;pidas c&oacute;mo sea posible. &iquest;Cu&aacute;nto? Pues depende del tipo de prueba y del proyecto. El autor no se moja en este aspecto, pero en mi opini&oacute;n deber&iacute;as mantener cada prueba por debajo de 1 segundo.</p><h3><em>Independent</em> o independientes</h3><p>Unas pruebas no deber&iacute;an depender de otras. Esto te permitir&aacute; ejecutar aisladamente las pruebas que fallen en lugar de tener que ejecutar toda la bater&iacute;a o un conjunto de pruebas.</p><h3><em>Repeatable</em> o repetibles</h3><p>El resultado de una prueba deber&iacute;a ser siempre el mismo y no variar si la ejecutas varias veces. De esta forma, podr&aacute;s ejecutar una prueba una y otra vez, hasta que arregles el error. De lo contrario tendr&iacute;as continuamente errores que luego no vas a poder reproducir.</p><h3><em>Self-validating</em> o validaci&oacute;n autom&aacute;tica</h3><p>Lo que quiere decir esta regla es que las pruebas no deber&iacute;an depender de una revisi&oacute;n, por ejemplo que el resultado fuera un texto que luego necesitar&aacute;s leer para saber si es correcto o no. La prueba debe pasar o no pasar, no deber&iacute;a haber otro resultado posible.</p><h3><em>Timely</em> o en el momento correcto</h3><p>El autor introduce en este cap&iacute;tulo las reglas del ciclo de TDD: rojo, verde y refactorizaci&oacute;n, pero no quiero profundizar mucho sobre este aspecto aqu&iacute;, porque tendremos el libro "Test Driven Development: By Example" por en este blog y en el canal de youtube m&aacute;s pronto que tarde.</p><h2>Show me the code</h2><p>Supongamos que tenemos la clase rectangulo que vimos en el cap&iacute;tulo de <a href="/post/codigo-limpio-estructuras-vs-objetos">estructuras vs objetos</a>.</p><pre><code class="php">class Rectangle
{
    private $height;
    private $width;

    public function __construct(float $height, float $width)
    {
        $this-&gt;height = $height;
        $this-&gt;width = $width;
    }

    public function area(): float
    {
        return round($this-&gt;height * $this-&gt;height, 2);
    }
}</code></pre><p>Escribir una prueba es una tarea muy sencilla, normalmente es simplemente una clase que tiene que extender de alg&uacute;n tipo de framework de pruebas, as&iacute; es como se hace con <code>phpunit</code></p><pre><code class="php">class RectangleTest extends \PHPUnit\Framework\TestCase
{
    public function test_area()
    {
        $rectangle = new Rectangle(1.11, 2.22);
        $this-&gt;assertSame(2.46, $rectangle-&gt;area());
    }
}</code></pre><p>F&aacute;cil, pero &iquest;que ocurre al ejecutarlo?</p><div class="alert alert-danger" role="alert">Failed asserting that 1.23 is identical to 2.46.</div><p>Efectivamente hab&iacute;a un error en el c&oacute;digo. En este caso lo hemos introducido a posta, pero es un tipo de error que se puede cometer f&aacute;cilmente.</p><p>&iquest;Has visto cual?</p>
]]></description><guid>https://devtia.com/post/codigo-limpio-pruebas-automaticas</guid><pubDate>Sat, 29 Aug 2020 11:32:50 +0200</pubDate></item><item><title>Código limpio: Gestión de errores</title><link>https://devtia.com/post/codigo-limpio-gestion-de-errores</link><description><![CDATA[<p>En la &uacute;ltima entrada vimos cual es la <a href="/post/codigo-limpio-no-hables-con-estranos">ley de demeter</a>, para que sirve y c&oacute;mo resolver el problema del acoplamiento a una estructura de clases a trav&eacute;s de la inyecci&oacute;n de dependencias. En esta entrada vamos a ver que deber&iacute;as tener en cuenta para mejorar la gesti&oacute;n de errores, como por ejemplo evitar el uso de c&oacute;digos de error, separar la l&oacute;gica de la gesti&oacute;n de errores y por supuesto evitar conocer los detalles de implementaci&oacute;n de las clases que hay por debajo. Cuando programamos adem&aacute;s de que nuestro c&oacute;digo sea limpio, vamos a tener que enfrentarnos a la sucia tarea de la gesti&oacute;n de errores.</p><p>Veamos un ejemplo con la clase responsable de notificar a los usuarios de <a href="/academy/">la academia</a> que hay un nuevo contenido disponible. En el m&eacute;todo <code>send</code> recibiremos un usuario y la entrada que debe serle notificada.</p><p>Partiremos de este primer ejemplo donde la gesti&oacute;n de errores ensucia el c&oacute;digo para ver cuales son las diferentes mejoras que podemos ir realizando.</p><pre><code class="php">class SendCommand extends AbstractCommand
{
    private function send(User $user, Post $post): void
    {
        $code = $this-&gt;mailer-&gt;sendTemplate(
            [$user-&gt;getEmail() =&gt; $user-&gt;getName()],
            $post-&gt;getName(),
            '@App/Command/Academy/Mailing/Post/post.html.twig',
            [
                'user' =&gt; $user,
                'post' =&gt; $post,
            ]
        );

        if (Code::TIMEOUT == $code) {
            sleep(20);
            $this-&gt;send($user, $post);
        } elseif (Code::ADDITIONAL_DATA_REQUIRED == $code) {
            $this-&gt;log(
                sprintf(
                    'message [%06d] for user "%s" could not be sent because was unavailable',
                    $post-&gt;getId(),
                    $user-&gt;getEmail()
                )
            );
        } elseif (Code::ADDITIONAL_DATA_REQUIRED == $code) {
            $this-&gt;log(
                sprintf(
                    'message [%06d] for user "%s" could not be sent because additional space was needed',
                    $post-&gt;getId(),
                    $user-&gt;getEmail()
                )
            );
        } elseif (Code::INBOX_IS_FULL == $code) {
            $this-&gt;log(
                sprintf(
                    'message [%06d] for user "%s" could not be sent because the inbox was full',
                    $post-&gt;getId(),
                    $user-&gt;getEmail()
                )
            );
        }
    }
}
</code></pre><p>Como se puede ver este ejemplo inicial tiene bastante que mejorar.</p><h2>Evita utilizar c&oacute;digos de error</h2><p>Los c&oacute;digos de error son <strong>dif&iacute;ciles de manejar</strong>. En general van a requerir un mont&oacute;n de estructuras if / else para poder lidiar con los diferentes c&oacute;digos de error.</p><p>Adem&aacute;s siempre cabe la posibilidad de que se a&ntilde;ada un nuevo c&oacute;digo de error que nosotros no tengamos capturado. En lugar de c&oacute;digos de error ser&iacute;a conveniente utilizar excepciones.</p><p>A continuaci&oacute;n vemos exactamente el mismo c&oacute;digo pero utilizando excepciones:</p><pre><code class="php">class SendCommand extends AbstractCommand
{
    private function send(User $user, Post $post): void
    {
        try {
            $this-&gt;mailer-&gt;sendTemplate(
                [$user-&gt;getEmail() =&gt; $user-&gt;getName()],
                $post-&gt;getName(),
                '@App/Command/Academy/Mailing/Post/post.html.twig',
                [
                    'user' =&gt; $user,
                    'post' =&gt; $post,
                ]
            );
        } catch (TimeoutException $e) {
            sleep(20);
            $this-&gt;send($user, $post);
        } catch (AdditionalDataRequiredException $e) {
            $this-&gt;log(
                sprintf(
                    'message [%06d] for user "%s" could not be sent because was unavailable',
                    $post-&gt;getId(),
                    $user-&gt;getEmail()
                )
            );
        } catch (ServiceUnavailableException $e) {
            $this-&gt;log(
                sprintf(
                    'message [%06d] for user "%s" could not be sent because additional space was needed',
                    $post-&gt;getId(),
                    $user-&gt;getEmail()
                )
            );
        } catch (InboxIsFullException $e) {
            $this-&gt;log(
                sprintf(
                    'message [%06d] for user "%s" could not be sent because the inbox was full',
                    $post-&gt;getId(),
                    $user-&gt;getEmail()
                )
            );
        }
    }
}</code></pre><p>De momento no hemos mejorado mucho y nuestro c&oacute;digo sigue teniendo una pinta terrible, pero estamos un paso m&aacute;s cerca de tener nuestro c&oacute;digo bastante m&aacute;s elegante.</p><h2>Separar l&oacute;gica y gesti&oacute;n de errores</h2><p>Lo que vamos a hacer ahora es separar la responsabilidad en dos m&eacute;todos. Uno de ellos contendr&aacute; la l&oacute;gica de negocio y el otro contendr&aacute; la gesti&oacute;n de errores. Este sencillo cambio hace nuestro c&oacute;digo mucho m&aacute;s legible y f&aacute;cil de mantener.</p><pre><code class="php">class SendCommand extends AbstractCommand
{
    private function handleSendException(User $user, Post $post, \Exception $exception): void
    {
        try {
            throw $exception;
        } catch (TimeoutException $e) {
            // ..
        } catch (AdditionalDataRequiredException $e) {
            // ..
        } catch (ServiceUnavailableException $e) {
            // ..
        } catch (InboxIsFullException $e) {
            // ..
        }
    }

    private function send(User $user, Post $post): void
    {
        try {
            $this-&gt;mailer-&gt;sendTemplate(
                [$user-&gt;getEmail() =&gt; $user-&gt;getName()],
                $post-&gt;getName(),
                '@App/Command/Academy/Mailing/Post/post.html.twig',
                [
                    'user' =&gt; $user,
                    'post' =&gt; $post,
                ]
            );
        } catch (\Exception$exception) {
            $this-&gt;handleSendException(user, $post, $exception);
        }
    }
}</code></pre><h2>Evita los detalles de implementaci&oacute;n</h2><p>Nuestro c&oacute;digo ha mejorado bastante, pero todav&iacute;a tiene un problema. Nuestro comando <strong>conoce los detalles de implementaci&oacute;n del sistema de env&iacute;o de correo</strong>. Esto supone un problema, si en el futuro quisi&eacute;ramos enviar el correo o las notificaciones con otra librer&iacute;a o a trav&eacute;s de otro medio, nuestro comando dejar&iacute;a de funcionar.</p><p>Para ello es conveniente evitar conocer los detalles de implementaci&oacute;n ( las excepciones ) que contiene el sistema de env&iacute;o, con lo que nos deber&iacute;a quedar algo as&iacute;.</p><pre><code class="php">class SendCommand extends AbstractCommand
{
    private function handleSendException(User $user, Post $post, \Exception $exception): void
    {
        $this-&gt;log(
            sprintf(
                'message [%06d] for user "%s" with message "%s"',
                $post-&gt;getId(),
                $user-&gt;getEmail(),
                $exception-&gt;getMessage()
            )
        );
    }

    private function send(User $user, Post $post): void
    {
        try {
            $this-&gt;mailer-&gt;sendTemplate(

                [$user-&gt;getEmail() =&gt; $user-&gt;getName()],
                $post-&gt;getName(),
                '@App/Command/Academy/Mailing/Post/post.html.twig',
                [
                    'user' =&gt; $user,
                    'post' =&gt; $post,
                ]
            );
        } catch (\Exception$exception) {
            $this-&gt;handleSendException($user, $post, $exception);
        }
    }
}</code></pre>
]]></description><guid>https://devtia.com/post/codigo-limpio-gestion-de-errores</guid><pubDate>Sat, 29 Aug 2020 11:31:17 +0200</pubDate></item><item><title>Código limpio: Funciones</title><link>https://devtia.com/post/codigo-limpio-funciones</link><description><![CDATA[<p>En esta entrada vamos a ver qu&eacute; caracter&iacute;sticas tienen o no tienen que tener <strong>nuestras funciones</strong> para que puedan considerase <strong>c&oacute;digo limpio</strong>. Para ello vamos a analizar el componente Lock de Symfony por ser un componente bastante sencillo de entender. Este componente crea y administra bloqueos, un mecanismo para proporcionar acceso exclusivo a un recurso compartido al m&aacute;s puro estilo de los sem&aacute;foros en el lenguaje de programaci&oacute;n c.</p><h2>Hacer una &uacute;nica cosa</h2><p>Una funci&oacute;n solo deber&iacute;a hacer una &uacute;nica cosa, y adem&aacute;s deber&iacute;a de ser ser capaz de hacerla bien. Este concepto a la vez que es sencillo de entender es bastante complejo de explicar, as&iacute; que vamos a definir algunas caracter&iacute;sticas que pueden indicarte que una de tus funciones hacen m&aacute;s de una cosa.</p><h3>Demasiado larga</h3><p>Si una funci&oacute;n tiene <strong>demasiadas l&iacute;neas de c&oacute;digo</strong>, es muy probable que est&eacute; haciendo varias cosas a la vez. Deber&iacute;as tratar de encontrar bloques dentro de esa misma funci&oacute;n que hagan una cosa concreta e ir extrayendolas en funciones m&aacute;s peque&ntilde;as.</p><p>El l&iacute;mite exacto para considerarse demasiado larga es un poco difuso, pero por encima de 20 l&iacute;neas deber&iacute;as al menos plantearte si tu funci&oacute;n es demasiado larga.</p><h3>Secciones</h3><p>Como continuaci&oacute;n a lo anterior, <strong>si una funci&oacute;n puede dividirse en secciones</strong>, nos encontramos ante un caso claro de que esa funci&oacute;n hace m&aacute;s de una cosa.</p><p>A continuaci&oacute;n vemos la funci&oacute;n <code>Lock::acquire</code></p><pre><code class="php">/**
 * {@inheritdoc}
 */
public function acquire(bool $blocking = false): bool
{
    try {
        if ($blocking) {
            if (!$this-&gt;store instanceof BlockingStoreInterface) {
                throw new NotSupportedException(sprintf('The store "%s" does not support blocking locks.', get_debug_type($this-&gt;store)));
            }
            $this-&gt;store-&gt;waitAndSave($this-&gt;key);
        } else {
            $this-&gt;store-&gt;save($this-&gt;key);
        }

        $this-&gt;dirty = true;
        $this-&gt;logger-&gt;info('Successfully acquired the "{resource}" lock.', ['resource' =&gt; $this-&gt;key]);

        if ($this-&gt;ttl) {
            $this-&gt;refresh();
        }

        if ($this-&gt;key-&gt;isExpired()) {
            try {
                $this-&gt;release();
            } catch (\Exception $e) {
                // swallow exception to not hide the original issue
            }
            throw new LockExpiredException(sprintf('Failed to store the "%s" lock.', $this-&gt;key));
        }

        return true;
    } catch (LockConflictedException $e) {
        $this-&gt;dirty = false;
        $this-&gt;logger-&gt;notice('Failed to acquire the "{resource}" lock. Someone else already acquired the lock.', ['resource' =&gt; $this-&gt;key]);

        if ($blocking) {
            throw $e;
        }

        return false;
    } catch (\Exception $e) {
        $this-&gt;logger-&gt;notice('Failed to acquire the "{resource}" lock.', ['resource' =&gt; $this-&gt;key, 'exception' =&gt; $e]);
        throw new LockAcquiringException(sprintf('Failed to acquire the "%s" lock.', $this-&gt;key), 0, $e);
    }
}</code></pre><p>Podemos observar 3 secciones principales. En la primera trata de adquirir el bloqueo, en la segunda comprueba si el bloqueo deber&iacute;a haber expirado y en el &uacute;ltimo bloque realiza el manejo de errores. Podr&iacute;amos facilitarle mucho la vida al lector si extrajeramos esos bloques dej&aacute;ndolos en algo similar a esto.</p><pre><code class="php">/**
 * {@inheritdoc}
 */
public function acquire(bool $blocking = false): bool
{
    try {
        $this-&gt;tryAcquire($blocking);
        $this-&gt;releaseIfExpired();

        return true;
    } catch (\Exception $e) {
        return $this-&gt;handleException($e);
    }
}</code></pre><h3>switch</h3><p>Un bloque switch es probablemente un indicador de que <strong>una funci&oacute;n hace varias cosas</strong>. La forma de solucionar esto es extraer ese bloque switch para que la &uacute;nica cosa que haga nuestra funci&oacute;n es decidir qu&eacute; hacer en funci&oacute;n del valor que le pasemos a switch.</p><p>A continuaci&oacute;n vemos un caso v&aacute;lido de un bloque switch dentro de la clase <code>Store\StoreFactory</code>, ya que aunque tiene un elemento switch la funci&oacute;n hace una &uacute;nica cosa, en este caso devolver la instancia de <code>Store\PersistingStoreInterface</code> correcta en funci&oacute;n del tipo de conexi&oacute;n que estemos utilizando.</p><pre><code class="php">/**
     * @param \Redis|\RedisArray|...
     *
     * @return PersistingStoreInterface
     */
    public static function createStore($connection)
    {
        if (!\is_string($connection) &amp;&amp; !\is_object($connection)) {
            throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be [...], "%s" given.');
        }

        switch (true) {
            case $connection instanceof \Redis:
            case $connection instanceof \RedisArray:
            case $connection instanceof \RedisCluster:
            case $connection instanceof \Predis\ClientInterface:
            case $connection instanceof RedisProxy:
            case $connection instanceof RedisClusterProxy:
                return new RedisStore($connection);
            // en total hay 32 casos diferentes.
        }

        throw new InvalidArgumentException(sprintf('Unsupported Connection: "%s".', $connection));
    }</code></pre><h2>Un s&oacute;lo nivel de abstracci&oacute;n</h2><p>Dentro de una misma funci&oacute;n debemos mantenernos siempre dentro del mismo nivel de abstracci&oacute;n.</p><p>Por ejemplo si tuvi&eacute;ramos una capa de dominio de negocio y una capa de persistencia de datos, dentro de una misma funci&oacute;n <strong>no deber&iacute;amos pasar de un nivel a otro</strong>, por lo cual tendr&iacute;amos funciones con l&oacute;gica de negocio y funciones con l&oacute;gica de persistencia de datos.</p><h2>Procesamiento de errores</h2><p><img alt="procesamiento de errores" loading="lazy" src="/cache/thumb_1200_0400/uploads/content/image/image/cacadb988f34f4c8084fcdecd5efc0ff23e25a7e.jpg" title="procesamiento de errores"></p><p>Empezaremos indicando que el procesamiento de errores es mucho m&aacute;s sencillo <strong>a trav&eacute;s de excepciones</strong> que de c&oacute;digos de error, pero esto lo veremos mucho m&aacute;s en profundidad en el cap&iacute;tulo de procesamiento de errores.</p><p>El problema que tienen los bloques <code>try / catch</code> es que dificultan mucho la lectura.Si tenemos una funci&oacute;n donde adem&aacute;s de la l&oacute;gica de la funci&oacute;n tiene uno o m&aacute;s bloques <code>try / catch</code>, probablemente deber&iacute;amos extraer la parte de la l&oacute;gica de negocio y dejar esa funci&oacute;n s&oacute;lamente con los bloques try catch tal y c&oacute;mo hicimos con la funci&oacute;n <code>Lock::acquire</code> en el ejemplo anterior.</p>
]]></description><guid>https://devtia.com/post/codigo-limpio-funciones</guid><pubDate>Wed, 03 Jun 2020 10:42:06 +0200</pubDate></item><item><title>¿Cómo actuar cuando cometemos un error?</title><link>https://devtia.com/post/como-actuar-cuando-cometemos-un-error</link><description><![CDATA[<p>Cualquier profesional se dedique al &aacute;mbito que se dedique, debe ser una garant&iacute;a de profesionalidad, estando lo suficientemente atento al trabajo que realiza y demostrando la seriedad necesaria para garantizar que no se cometan errores tontos e innecesarios.</p><p>Sin embargo, aunque suene a t&oacute;pico, <strong>somos seres humanos y estamos expuestos a cometer errores</strong> que, sin lugar a dudas, perjudicar&aacute;n a nuestros clientes. C&oacute;mo afrontes este error puede dar lugar a <strong>dos finales totalmente distintos</strong>:</p><ul><li>Puedes perder toda la confianza que hayas podido ganar como profesional y parecer una persona incompetente que probablemente no seas.</li><li>Puedes actuar de manera profesional, no excus&aacute;ndote del error, ni echando balones fuera, demostrando as&iacute; tu val&iacute;a como profesional y recuperando la confianza perdida de tu cliente.</li></ul><p>Actuar bajo la presi&oacute;n de los errores no es una tarea en absoluto f&aacute;cil. Hemos elaborado esta peque&ntilde;a gu&iacute;a para que sepas c&oacute;mo hacerlo de la mejor manera posible. Est&aacute; muy orientada al trabajo que realizamos en DEVTIA: Desarrollo de software a medida, pero seguro que puedes aplicar estos consejos a cualquier tipo de trabajo.</p><h2>Mant&eacute;n la calma</h2><p><img alt="62fdddcadd6ff7b2fe1865f99274e9a820905b68.jpg" src="/cache/thumb_1200_0400/uploads/content/image/image/62fdddcadd6ff7b2fe1865f99274e9a820905b68.jpg" loading="lazy"></p><p>Antes de tomar cualquier tipo de decisi&oacute;n, lo primero que deber&iacute;as hacer es respirar y lograr mantenerse lo suficientemente tranquilo como para saber que la decisi&oacute;n que tomes a continuaci&oacute;n va a ser la correcta. Los nervios no son buenos compa&ntilde;eros en este tipo de situaciones.</p><p>Una vez en calma, empieza a actuar de manera progresiva. En primer lugar, tienes que impedir que el error, venga de donde venga, se siga propagando y acabe por producir da&ntilde;os mucho mayores.</p><p>Por ejemplo, si tienes un comercio electr&oacute;nico y has estado realizando ventas, pero a la hora de intentar pagar la pasarela de pago no ha funcionado de manera correcta, lo primero que deber&iacute;as poner ser&iacute;a un mensaje del tipo &ldquo;ahora mismo no podemos procesar su pedido, int&eacute;ntelo de nuevo m&aacute;s tarde&rdquo; o &ldquo;d&eacute;jenos su email y le avisaremos en cuanto la pasarela de pago se encuentre disponible&rdquo;.</p><h2>Informa al responsable</h2><p>A veces, algunas personas tratan de ocultar sus errores y solucionarlos en la sombra, sin que nadie se entere. Este comportamiento no deber&iacute;a darse nunca en un buen profesional.</p><p><strong>La honestidad y la transparencia</strong> han de ser tu pol&iacute;tica a seguir en estos casos, avisando lo antes posible del error al responsable y explicando claramente qu&eacute; ocurri&oacute; y por qu&eacute;. En este momento es esencial transmitir que no se est&aacute;n buscando responsables ni culpables, sino que <strong>todos est&aacute;is remando hac&iacute;a una misma meta</strong>: la soluci&oacute;n del problema.</p><p>Adem&aacute;s de informar al responsable, deber&aacute;s explicarle, cu&aacute;les son <strong>las soluciones que tu propones</strong> y qu&eacute; implica cada una de ellas.</p><h2>Pide ayuda</h2><p>Todo el mundo comete errores y la peor actitud posible es trag&aacute;rtelos t&uacute; solo.</p><p>As&iacute; que <strong>no dudes en pedir ayudar a tus compa&ntilde;eros</strong> m&aacute;s cercanos, ellos tambi&eacute;n cometen o cometer&aacute;n errores y se habr&aacute;n visto en situaciones similares. No tengas miedo en contar con ellos.</p><p>En momentos as&iacute; y por el bien de la empresa, todos deber&iacute;an estar dispuestos a ayudar, no importa a qui&eacute;n pidas ayuda, lo importante es que sea una ayuda incondicional, de esta manera tambi&eacute;n <strong>se reforzar&aacute;n no solo las relaciones</strong> profesionales, sino tambi&eacute;n las personales.</p><p>Cuando el error no lo cometas t&uacute;, no dudes en estar disponible para aquel que lo haya cometido. Adopta la actitud que te gustar&iacute;a que adoptar&aacute;n contigo.</p><h2>Actua despacio</h2><p><img alt="115a7c874a7aa0bc22ea5314235d428e6bbf9006.jpg" src="/cache/thumb_1200_0400/uploads/content/image/image/115a7c874a7aa0bc22ea5314235d428e6bbf9006.jpg" loading="lazy"></p><p>Al igual que la ansiedad, <strong>la prisa es un enorme enemigo a la hora de solucionar un error</strong>. Cuando los errores se intentan solucionar r&aacute;pidamente cabe la posibilidad de que se cometan otros m&aacute;s graves, entrando en un bucle del que es complicado salir.</p><p><strong>La paciencia ser&aacute; la mejor de las virtudes</strong> en este tipo de situaciones.</p><p>Piensa que el error ya est&aacute; hecho y que a todas las personas a quienes afecta directa o indirectamente ya saben de su existencia. Ya no tienen ninguna prisa, ahora lo importante es <strong>mantener la cabeza fr&iacute;a y hacer un buen trabajo</strong> para solucionarlo.</p><p>Es mejor una soluci&oacute;n que lleve su tiempo, que una r&aacute;pida que no resuelva el problema.</p><h2>Aprende</h2><p>Una vez las cosas han vuelto a su cauce, lo mejor es <strong>analizar qu&eacute; es lo que sali&oacute; mal y c&oacute;mo evitar una situaci&oacute;n similar en el futuro</strong>.</p><p>Reflexionando y cambiando los procedimientos que indujeron al error, se est&aacute; demostrando una actitud proactiva y un enfoque constructivo en vez de derrotista.</p><p>&iquest;Hab&iacute;a falta de conocimiento?, &iquest;Falta quiz&aacute; de comunicaci&oacute;n?, &iquest;Fall&oacute; la concentraci&oacute;n?, &iquest;Era un error evitable?... Un buen an&aacute;lisis del origen del fallo ser&aacute; esencial para aprender de los errores propios y afrontar el futuro siendo un equipo mejor y m&aacute;s cohesionado.</p>
]]></description><guid>https://devtia.com/post/como-actuar-cuando-cometemos-un-error</guid><pubDate>Tue, 21 Jan 2020 22:34:00 +0100</pubDate></item></channel></rss>