Vamos a hacer un pequeño resumen de lo que tenemos hasta ahora.

  • En el primer capítulo, empezamos haciendo un listado de resultados de álbumes de música.
  • En el segundo capítulo, introducimos el patrón llamado MVVM.
  • En el tercer capítulo, introducimos la capa de dominio; muy útil cuando estamos diseñando una aplicación grande. Aunque, también para aplicaciones pequeñas.
  • Y, en el capítulo anterior, terminamos una primera iteración, añadiendo la capa de Data, y así poder hacer una llamada a un servicio. Además, pusimos algún elemento interesante, como una lógica para tratar resultados paginados.

En este capítulo, espero más corto que el anterior, vamos a dividir el proyecto por capas y veremos qué está pasando. Si eres un developer que viene de Objective-C, recordarás que en todos los archivos .h y .m teníamos que hacer import a todo. Con la llegada de Swift esto se terminó. ¿Bien, no? Bueno, sí y no. Lo que ocurre en Swift, es que al no hacer imports a ningún archivo que esté en nuestro namespace, se nos puede olvidar a qué capa van las cosas. En otras palabras, que es muy sencillo romper la arquitectura de la aplicación, añadiendo dependencias de un sitio a otro.

¿Como evitar esta situación? Pues muy sencillo, creando diferentes frameworks.

Crearemos un primer framework y pondremos tanto Data como Domain en ese framework. Luego, repetiremos el paso, creando un framework para Data.

Lo primero que haremos es crear un nuevo target y crearemos un framework.

Lo llamaremos DomainLayer. Ahora abre el Podfile y lo actualizaremos.

Date cuenta que en SearchMusic representa la capa de aplicación (o, esa es la idea). No necesitamos Moya en la capa de aplicación, ni SnapKit. Tampoco necesitamos RxDataSources en la capa de Dominio.

Ahora, en el proyecto tendremos una carpeta nueva. Arrastra el contenido de la carpeta Domain, a esta nueva carpeta llamada DomainLayer, esto es, la carpeta UseCases y la carpeta Entities. Haz lo mismo con la carpeta Data.

Borra la carpeta Domain. Ya no la vamos a necesitar. Ahora vamos a compilar. Mmmm, ¿no ha pasado nada? Vale, si. Tenemos que cambiar el target de los archivos, moverlos de sitio, sencillamente no hace nada.

Cambia en todos los archivos que hay dentro de DomainLayer, su target, de forma que ahora pertenezcan al nuevo framework.

Compilamos y ahora sí. Muchos errores. Vamos por pasos.

  • En el SceneDelegate, importaremos DomainLayer

Lo haremos también en el ListViewModel. Y tiene sentido, de momento, hacerlo en esos dos sitios.

  • Con hacer imports no es suficiente. Se necesita que las entidades se declaren como públicas y sus funciones también.

Necesitamos que los constructores también sean públicos, si es que los usamos. Haremos lo mismo con DiscogsRepository allí donde nos haga falta hacer público.

Pero, el compilador nos pide, además, imports en el ListTableViewCell, en el ListSectionModel y en el ListSectionItem. ¿Por qué?

Porque estamos usando la entidad Album en el DataSource. Ya hemos encontrado una primera dependencia de la capa de Dominio en la capa de Aplicación. La resolveremos al final.

  • En Album haremos lo siguiente.

Por último, el compilador nos pide el fichero TransformType. Aquí hemos encontrado otra cosa que resolveremos más adelante. Por ahora, crea un archivo dentro del Dominio y copia su contenido.

Ya tendríamos el framework DomainLayer separado y hemos detectado una dependencia en Album. Vamos ahora a crear el framework DataLayer.

Crearemos un nuevo framework DataLayer y moveremos el contenido de Data ahí.

El fichero Podfile tendrá un aspecto similar a este.

Tendrás que cambiar el target de cada fichero a DataLayer. Como hicimos en DomainLayer.

Pero, está pasando algo raro. Veamos. Tienes que borrar DataLayer como dependencia de SearchMusic.

DataLayer no depende de SearchMusic, sino de DomainLayer. En DomainLayer, tendremos esto.

Ahora nos queda ir resolviendo todos los errores, poco a poco. Lo primero, que las clases, los métodos y las propiedades que se usen en otra capa, se tienen que declarar como públicos. Con eso, todo se resuelve.

Iremos a DiscogsRepository.swift. Al pertenecer en Data, el repository no conoce nada de Dominio, por lo tanto, nos quedaremos con su DTO.

Tenemos que declarar AlbumDTO público.

Ahora que tenemos los frameworks, no sería necesario usar la coletilla DTO. Usemos Album directamente. Usa la herramienta Refactor y renómbralo a Album.

Ahora, vamos a por los errores en DomainLayer. SearchUseCase se quedará así.

Nada, extraño, salvo la transformación que hacemos de la representación de álbumes en la capa de Data y la representación de Album en la capa de Dominio. Lo resolveremos así. Album seguirá así.

Y, ahora crea un fichero, Album+Data.swift. Fíjate que no es lo mismo Album que DataLayer.Album.

Con esto, ya tendríamos la capa de Dominio bien. Ahora vamos con la de Aplicación.

¿Qué problema tenemos en la capa de aplicación? Que estamos usando un modelo de Dominio en la capa de Aplicación. Esto, puede ser un problema o no. El primer indicador es ver qué ficheros están importando dicho modelo para darse cuenta.

Si nos fijamos, la celda no representa un álbum, representa una forma de visualizar 4 elementos por resultado. La celda no es más que un resultado, con un título, un subtitulo, algo en la izquierda y algo en la derecha. ¿Por qué no hacemos algo parecido en el código?

Veamos.

Crea SearchViewModel.swift dentro de Cells.

Luego, crea un SearchViewModel+Domain.swift

Ya tenemos los constructores de este nuevo view model, listo. Ahora cambiemos el datasource. Borra el actual o bien reemplázalo. No lo llamaremos ListSectionModel, ahora lo llamaremos SearchSectionModel

Y ahora, haremos lo mismo con SearchSectionItem.swift.

Actualizaremos la celda a SearchTableViewCell.

Hay que actualizar la celda del datasource en el view controller.

Por último, en el view model, actualizaremos ciertos nombres que cambiaron (esto solo se haría si no le diste a la herramienta refactorizar). En el componente TableView también hay que cambiar el nombre de la celda.

Y ya lo tendríamos.

Recuerda, crear frameworks es muy interesante si se tiene idea de crear una aplicación separada por tres capas. Además, previene de errores típicos como el acceso a información de forma no adecuada. Los imports nos hacen pensar y así tiene que ser.

Nos queda, una cosa. El repository que tenemos se ha quedado un poco raro. Lo tenemos en Dominio. Es correcto ya que un UseCase solo tiene que entender por sus elementos, pero tenemos que hacer algún cambio.

Además, ¿y los tests? Los tests estaban en el proyecto principal y ahora tenemos frameworks. Y tenemos un TransformType repetido tres veces (en cada una de las capas) que no me gusta nada.

De esto irá la siguiente parte. Repositories, DataSources y más tests.

--

--