<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Horacio López</title>
    <description>The latest articles on DEV Community by Horacio López (@hdlopez).</description>
    <link>https://dev.to/hdlopez</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F254157%2Fc07771a9-271f-48f6-a1cc-389fa0c05fda.jpg</url>
      <title>DEV Community: Horacio López</title>
      <link>https://dev.to/hdlopez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hdlopez"/>
    <language>en</language>
    <item>
      <title>¿Como estructurar tu aplicación en Go?</title>
      <dc:creator>Horacio López</dc:creator>
      <pubDate>Mon, 10 May 2021 01:53:09 +0000</pubDate>
      <link>https://dev.to/hdlopez/como-estructurar-tu-aplicacion-en-go-4hk2</link>
      <guid>https://dev.to/hdlopez/como-estructurar-tu-aplicacion-en-go-4hk2</guid>
      <description>&lt;h2&gt;
  
  
  Objetivo
&lt;/h2&gt;

&lt;p&gt;Cuando comencé a programar en &lt;a href="https://golang.org/" rel="noopener noreferrer"&gt;go&lt;/a&gt;, me hice muchas preguntas. Preguntas sobre el lenguaje en sí, buenas prácticas, code conventions, naming conventions, cómo escribir código idiomático, etc,... pero creo que una de mis primeras preguntas fue: &lt;strong&gt;¿cómo estructuro mi aplicación?&lt;/strong&gt;. Luego de haber investigado y haber escrito un par de aplicaciones productivas, &lt;strong&gt;mi idea es compartirles una propuesta de cómo estructurar una aplicación en golang (o simplemente &lt;em&gt;go&lt;/em&gt;) y dejarles un&lt;/strong&gt; &lt;a href="https://github.com/hdlopez/clean-architecture-golang" rel="noopener noreferrer"&gt;ejemplo en GitHub&lt;/a&gt; fácil de utilizar.&lt;/p&gt;

&lt;p&gt;Si buscan en internet realmente hay muchas, muchas, propuestas e ideas (al final comparto algunos links). Muchas de esas basadas en la propuesta de &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;Clean Architecture&lt;/a&gt; de Uncle Bob y en &lt;a href="https://martinfowler.com/bliki/DomainDrivenDesign.html" rel="noopener noreferrer"&gt;Domain Driven Design&lt;/a&gt;. En este artículo les comparto una propuesta más, basada en clean architecture, inspirada en artículos que he leído y en español :).&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean Architecture? y eso?
&lt;/h2&gt;

&lt;p&gt;Como mencionaba, en &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;este&lt;/a&gt; gran artículo de hace ya varios años,  &lt;em&gt;Uncle Bob&lt;/em&gt; describe cuáles considera que deben ser las características de una buena estructura o modularización de una aplicación.&lt;/p&gt;

&lt;p&gt;Intentaré describir en español (o spanglish) y usando un poco mis palabras lo que se menciona en el artículo. &lt;/p&gt;

&lt;p&gt;Las aplicaciones deben ser:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;em&gt;Independientes de frameworks:&lt;/em&gt; la arquitectura no debe tener dependencias con frameworks subyacentes que utilicemos. Esto nos permite flexibilidad ante cambios de framework y no atarnos a las restricciones que cada uno presente .&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Testeable&lt;/em&gt;: los componentes de la aplicación deben ser testeables, sin necesidad de otros módulos o de tener una UI. &lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Independiente de la UI&lt;/em&gt;:  la interfaz con el usuario de la aplicación podría ser un command line, una API, una web y eso debería ser fácilmente intercambiable sin cambiar las reglas de negocio.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Independiente de la base de datos&lt;/em&gt;: la forma en que se almacenan los datos debe ser independiente de tus reglas de negocio. Si la aplicación comienza almacenando datos en mysql y luego evoluciona y debe simplemente hacer un &lt;em&gt;POST&lt;/em&gt; de esa información a un API externa, deberían ser intercambiables sin modificar reglas de negocio.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Independiente de cualquier ente externo&lt;/em&gt;: basicamente las reglas de negocio no deberían saber de nada de lo que sucede por fuera de ellas, ni de DBs, ni de APIs o de cualquier otra cosa.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Siguiendo estos principios según Uncle Bob podemos &lt;strong&gt;separar nuestro código en 4 capas&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Entities&lt;/em&gt;: esta capa encapsula las reglas de negocio de nuestro dominio. Normalmente en go estas entidades son representadas por structs y sus funciones asociadas.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Use cases&lt;/em&gt;: esta capa contiene reglas de negocio específicas de nuestra aplicación. Aquí se proveen los servicios para cumplir los casos de uso.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Interface Adapters / Controller&lt;/em&gt;: esta capa consiste en una serie de adaptadores que toman los datos en el formato que los envía el usuario y los transforma para que puedan ser utilizados por nuestra capa de casos de uso.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Framework &amp;amp; Driver&lt;/em&gt;: esta capa está generalmente compuesta de conectores o frameworks que nos permiten adaptarnos a distintos entes externos, como base de datos, APIs, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ahora que conocemos más de clean architecture, apliquemos estos principios y separación en capas a una aplicación en go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aplicando Clean Architecture en Go
&lt;/h2&gt;

&lt;p&gt;Utilizaremos como base de la explicación una  &lt;a href="https://github.com/hdlopez/clean-architecture-golang" rel="noopener noreferrer"&gt;API de mensajes&lt;/a&gt;. ¿Por qué una API de mensajes? Solo porque quise salir de la clásica aplicación de los ejemplos que manejan usuarios 👨🏻‍💻. La API que utilizaremos maneja una entidad &lt;code&gt;Message&lt;/code&gt; que solo tiene como dato un string, siendo ese string el texto del mensaje (si lo sé, me maté con el ejemplo 😅). Mi idea no es centrarme en una aplicación compleja a nivel lógica de negocio, sino simplemente usarla para mostrar su estructura.&lt;/p&gt;

&lt;p&gt;Si visualizamos el proyecto en GitHub o descargamos el ejemplo, la carpeta &lt;em&gt;root&lt;/em&gt; se verá más o menos así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;drwxr-xr-x  14 hlopez  staff   448 Nov  3 16:17 &lt;span class="nb"&gt;.&lt;/span&gt;
drwxr-xr-x   3 hlopez  staff    96 Oct 25 18:10 ..
drwxr-xr-x   5 hlopez  staff   160 Oct 30 19:30 api
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1 hlopez  staff   198 Oct 25 19:39 main.go
drwxr-xr-x   5 hlopez  staff   160 Nov  6 18:12 message
drwxr-xr-x   4 hlopez  staff   128 Oct 30 20:56 restclient
...
...
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos ver, tenemos básicamente 3 módulos &lt;code&gt;api&lt;/code&gt;, &lt;code&gt;message&lt;/code&gt; y &lt;code&gt;restclient&lt;/code&gt;. Existen algunos módulos más en la aplicación, pero son utilitarios y no son relevantes estructuralmente hablando. &lt;/p&gt;

&lt;p&gt;Relacionando los módulos con las capas de &lt;em&gt;clean architecture&lt;/em&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;api&lt;/em&gt; - contiene el código que se ubica en la capa &lt;em&gt;Controller&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;message&lt;/em&gt; - este módulo contiene código de la capa &lt;em&gt;Entities&lt;/em&gt; y de la capa &lt;em&gt;Use cases&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;** &lt;em&gt;restclient&lt;/em&gt; - contiene código que se ubica en la capa &lt;em&gt;Framework &amp;amp; drivers&lt;/em&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;** El módulo &lt;em&gt;restclient&lt;/em&gt; es solo un ejemplo, pero podríamos tener más módulos en la capa "Frameworks &amp;amp; drivers" como accesos a mysql, a elastic search, a key value stores (como cassandra), etc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;La aplicación puede ser iniciada haciendo simplemente &lt;code&gt;go run main.go&lt;/code&gt;. El código en &lt;code&gt;main.go&lt;/code&gt; es extremadamente sencillo.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;main.go&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Dependency injection section&lt;/span&gt;
    &lt;span class="n"&gt;clients&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RestClients&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;msgAPI&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;restclient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewMessageAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MessageAPI&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;msgRepo&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msgAPI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;msgSrv&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msgRepo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;msgCtrl&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewMessageController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msgSrv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Creates the API intance&lt;/span&gt;
    &lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msgCtrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Runs the application&lt;/span&gt;
    &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como se puede ver, la función &lt;code&gt;main()&lt;/code&gt; es la encargada de inicializar los módulos y sus dependencias, para luego iniciar la aplicación usando la función &lt;code&gt;Run()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;En la siguientes secciones describo el por qué de la existencia de cada módulo (comenzando con el módulo &lt;em&gt;api&lt;/em&gt;). La idea es explicar brevemente las implementaciones y hacia el final ver cómo esta arquitectura nos beneficia en el unit testing.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;En todos los snippets de código no se muestra el código completo, con imports y funciones auxiliares por cuestiones de simplicidad. El código completo está disponible en &lt;a href="https://github.com/hdlopez/clean-architecture-golang" rel="noopener noreferrer"&gt; GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Módulo "api"
&lt;/h3&gt;

&lt;p&gt;El módulo &lt;em&gt;api&lt;/em&gt; está en la capa &lt;em&gt;Controller&lt;/em&gt;. Su objetivo es proveer al usuario medios de interactuar con la capa de servicios (&lt;em&gt;Use cases&lt;/em&gt;). En este caso, la interfaz para el usuario es de tipo REST API y está implementada utilizando en el framework &lt;a href="https://github.com/gin-gonic/gin" rel="noopener noreferrer"&gt;gin-gonic&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;api/api.go&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pingCtrl&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pingCtrl&lt;/span&gt;
    &lt;span class="n"&gt;msgCtrl&lt;/span&gt;  &lt;span class="n"&gt;MessageController&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;configRoutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;configRoutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/ping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pingCtrl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/messages/:id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;msgCtrl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El tipo &lt;code&gt;API&lt;/code&gt; tiene como propiedades los distintos controllers que manejarán el input del usuario y lo transformarán para enviar a la siguiente capa. Un ejemplo, es el caso de &lt;em&gt;message controller&lt;/em&gt; definido con el tipo &lt;code&gt;messageCtrl&lt;/code&gt; en el archivo &lt;code&gt;messagectrl.go&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;api/messagectrl.go&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;MessageController&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;Ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// messageCtrl handles message entity&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;messageCtrl&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;srv&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctrl&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;messageCtrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;Ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// 1 - Unmashall user parameters from gin.Context&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// 2 - Check and handle validation errors (no business validation)&lt;/span&gt;

    &lt;span class="c"&gt;// 3 - Make what you need with your request. In this case, get the message by ID.&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ctrl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;srv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este ejemplo, la función &lt;code&gt;Get&lt;/code&gt; asociada a &lt;code&gt;messageCtrl&lt;/code&gt; toma los parámetros del usuario, los valida y luego los envia a la capa de servicios. Ignoremos en este caso el uso de la variable &lt;code&gt;srv&lt;/code&gt; del tipo &lt;code&gt;Service&lt;/code&gt; que veremos en la siguiente sección.&lt;/p&gt;

&lt;h3&gt;
  
  
  Módulo &lt;em&gt;message&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Para comenzar, es bueno mencionar que el nombre del módulo refiere al domino de la aplicación, en este caso "mensajes". En este módulo se definen los objetos de dominio que se manejarán y las funciones que implementarán los casos de uso. &lt;/p&gt;

&lt;p&gt;En este caso la entidad a manejar es &lt;code&gt;Message&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;message/message.go&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"text"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Extremadamente simple, solo contiene un string que almacena el texto del mensaje. Esta es la entidad que se expone hacia afuera para uso de la capa &lt;em&gt;Controller&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Dentro del módulo &lt;em&gt;message&lt;/em&gt;, se tiene también el tipo &lt;code&gt;Service&lt;/code&gt;. Esta interfaz expone las funciones que implementan los casos de uso (capa de &lt;em&gt;Use cases&lt;/em&gt;). En el ejemplo de la API de mensajes el &lt;strong&gt;caso de uso&lt;/strong&gt; es muy simple:  &lt;strong&gt;Obtener un mensaje por ID&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;message/service.go&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Service&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;messageSrv&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="n"&gt;Repository&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srv&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;messageSrv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// validate parameters depending your business logic&lt;/span&gt;
    &lt;span class="c"&gt;// example: ID must be an UUID v4&lt;/span&gt;

    &lt;span class="c"&gt;// business logic goes here ...&lt;/span&gt;

    &lt;span class="c"&gt;// retrieve message using its repository&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;srv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// do some stuff&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notar que &lt;code&gt;Service&lt;/code&gt; no tiene mayores dependencias más que con la interfaz &lt;code&gt;Repository&lt;/code&gt; (tipo que describiremos en breve). Eso hace que la lógica de negocio sea agnóstica a cualquier cambio a nivel almacenamiento. &lt;/p&gt;

&lt;p&gt;En la función &lt;code&gt;Get&lt;/code&gt; asociada al tipo &lt;code&gt;messageSrv&lt;/code&gt; se deben validar los parámetros y luego ejecutar las reglas de negocio correspondientes. En este caso podría ser tan simple como obtener el mensaje desde su repositorio.&lt;/p&gt;

&lt;p&gt;Respecto al tipo &lt;code&gt;Repository&lt;/code&gt; es una interfaz que brinda una abstracción del acceso a datos. Este código se podría considerar también en la de capa &lt;em&gt;Use cases&lt;/em&gt;, en donde los casos de uso que se implementan son los más básicos como: obtener o guardar un &lt;code&gt;Message&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;message/repository.go&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Repository&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;msgRepo&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// It can be easly changed by a database or other storage without touching&lt;/span&gt;
    &lt;span class="c"&gt;// business logic&lt;/span&gt;
    &lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="n"&gt;restclient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MessageAPI&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msgRepo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Getting message from the external API.&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conceptualmente los repositorios de datos deben interactuar con manejadores de base de datos o conectores con APIs para obtener, almacenar o eliminar información. En el caso del ejemplo, el repositorio realiza una conexión con una API externa que brinda mensajes. En la función &lt;code&gt;Get&lt;/code&gt; del tipo &lt;code&gt;msgRepo&lt;/code&gt; se hace uso del módulo &lt;code&gt;restclient&lt;/code&gt; para lograr dicha conexión.&lt;/p&gt;

&lt;h3&gt;
  
  
  Módulo "restclient"
&lt;/h3&gt;

&lt;p&gt;El módulo &lt;em&gt;restclient&lt;/em&gt; está en la capa &lt;em&gt;Framework &amp;amp; driver&lt;/em&gt;. En esta capa la idea es brindar conectores con frameworks u otro entes externos logrando que posibles cambios entre conectores no afecten a la lógica de negocio. Como ya hemos repasado, este es solo un ejemplo, pero podríamos tener más módulos en la capa "Frameworks &amp;amp; drivers" como accesos a mysql, a elastic search, a key value stores (como cassandra), etc.&lt;/p&gt;

&lt;p&gt;En este caso, en el módulo restclient se implementa el acceso a una API utilizando el framework &lt;a href="https://github.com/go-resty/resty" rel="noopener noreferrer"&gt;resty&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;restclient/messageapi.go&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;restclient&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;MessageAPI&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;msgAPI&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;restAPI&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="c"&gt;// Get a message from our external Message API&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msgAPI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// type assertion&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;restclient/restclient.go&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;restclient&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;restAPI&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;readClient&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;resty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;restAPI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;

    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// handling error and returns the response properly&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se utiliza la composición de tipos en go, componiendo el tipo &lt;code&gt;restAPI&lt;/code&gt; en &lt;code&gt;msgAPI&lt;/code&gt;. En el tipo &lt;code&gt;msgAPI&lt;/code&gt; se aprovecha de una implementación genérica de GET HTTP usando un cliente rest de &lt;code&gt;resty&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Y la testeabilidad??!
&lt;/h3&gt;

&lt;p&gt;Venimos enfocados en organización, dependencia entre módulos, organización de capas, pero no hablamos aún de algo &lt;strong&gt;muy importante&lt;/strong&gt; que es el &lt;strong&gt;testing&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Dada la estructura planteada y la independencia entre capa y capa, es muy sencillo realizar pruebas unitarias de cada uno de nuestros módulos sin depender de módulos externos.&lt;/p&gt;

&lt;p&gt;Debajo  muestro un ejemplo de cómo probar las funciones de la capa &lt;em&gt;Use cases&lt;/em&gt;, en particular del archivo &lt;code&gt;service.go&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;message/service_test.go&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;mockRepo&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;mockRepo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"error"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Mocked error"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"TestMessage"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewInmemRepository&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;Repository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mockRepo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Test_messageSrv_Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// creates in memory message repository&lt;/span&gt;
    &lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewInmemRepository&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c"&gt;// create new service instance in order to test&lt;/span&gt;
    &lt;span class="n"&gt;srv&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NewService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;    &lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt;    &lt;span class="n"&gt;args&lt;/span&gt;
        &lt;span class="n"&gt;want&lt;/span&gt;    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;
        &lt;span class="n"&gt;wantErr&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"test OK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"myMessageID"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"TestMessage"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"test fail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tt&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;got&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;srv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wantErr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"messageSrv.Get() error = %v, wantErr %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wantErr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeepEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;got&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;want&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"messageSrv.Get() = %v, want %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;got&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;want&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como vemos en el ejemplo, en este caso es muy sencillo implementar un "mock" que nos permita probar la lógica de la función &lt;code&gt;Get&lt;/code&gt; sin depender de la lógica subyacente del repositorio (no dependemos si utilizamos una DB, una API, o cualquier otro framework). &lt;/p&gt;

&lt;p&gt;En el mock implementado en el ejemplo simulamos con el string "error", un caso de error en el repositorio. De esa forma podemos plantear un caso de éxito y un caso de error muy fácilmente y sin depender de otros módulos.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TIP&lt;/strong&gt; con &lt;a href="https://github.com/cweill/gotests" rel="noopener noreferrer"&gt;esta&lt;/a&gt; herramienta en go pueden generar unos hermosos test siguiendo el patrón de &lt;a href="https://en.wikipedia.org/wiki/Data-driven_testing" rel="noopener noreferrer"&gt;Data Driven Testing (DDT)&lt;/a&gt; (o también conocido como Table Driven Testing o TDT)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Luego de leer tutoriales, hacer pruebas de concepto, de probar, de equivocarme, de intentar generar código idiomático en &lt;em&gt;go&lt;/em&gt;, luego de haber leído decenas de artículos usando los principios de &lt;em&gt;Uncle Bob&lt;/em&gt; y su famosa &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;clean architecture&lt;/a&gt;, finalmente, este es  &lt;strong&gt;mi humilde aporte a la comunidad (en español) de cómo estructurar tu aplicación&lt;/strong&gt; en &lt;em&gt;go&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Usando la estructura del ejemplo de la API de mensajes se puede extrapolar a cualquier otra aplicación. En resumen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;em&gt;api&lt;/em&gt;: en este caso nos da la interfaz con el usuario mediante una rest API, pero podría ser un command line u cualquier otro tipo de interfaz. El nombre del módulo cambiaría según el caso.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;message&lt;/em&gt;: en este módulo podemos encapsular nuestra lógica de negocio y casos de uso. El nombre del módulo refiere al domino de la aplicación por lo que podría ser cualquier cosa. Deben ser nombres en singular siguiendo &lt;a href="https://talks.golang.org/2014/names.slide" rel="noopener noreferrer"&gt;naming conventions&lt;/a&gt; de go. Ejemplo: user, customer, item, etc. &lt;/li&gt;
&lt;li&gt;
&lt;em&gt;restclient&lt;/em&gt;: este es un simple ejemplo de un módulo externo para dar servicios a la capa de &lt;em&gt;Use case&lt;/em&gt;. Otros ejemplos podrían ser, módulos con namings como mysqlhandler, dbhandler, elastichandler, dbutil, siendo todos ellos conectores a distintos gestores de datos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En &lt;a href="https://github.com/hdlopez/clean-architecture-golang" rel="noopener noreferrer"&gt;mi repositorio de GitHub&lt;/a&gt; dejo un ejemplo totalmente funcional que pueden utilizar libremente.&lt;/p&gt;

&lt;p&gt;Happy structuring :D (creo que inventé la expresión...)&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://rakyll.org/typesystem/" rel="noopener noreferrer"&gt;Go for newcomers&lt;/a&gt; - Excelente para los más nuevos en go&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://gobyexample.com/" rel="noopener noreferrer"&gt;Go By example&lt;/a&gt; - Una página con un enfoque MUY práctico llena de ejemplos de código y que es posible probar en el playground.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://talks.golang.org/2014/names.slide" rel="noopener noreferrer"&gt;What's in a name&lt;/a&gt; - Presentación sobre naming conventions en go&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;Uncle Bob - Clean Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/@eminetto/clean-architecture-using-golang-b63587aa5e3f" rel="noopener noreferrer"&gt;Clean Architecture Using Golang&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://manuel.kiessling.net/2012/09/28/applying-the-clean-architecture-to-go-applications/" rel="noopener noreferrer"&gt;Applying The Clean Architecture to Go applications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>spanish</category>
      <category>programming</category>
      <category>structuring</category>
    </item>
  </channel>
</rss>
