Skip to content

fernandospr/android-movies

Repository files navigation

CircleCI

Android Movies

Android Movies es una app Android desarrollada en Kotlin que utiliza la API de The Movie Database para mostrar películas y series.

Main-Detail Detail-Video Search
android-movies-main-detail.mp4
android-movies-detail-youtube.mp4
android-movies-search-detail.mp4

Cómo correr la app

  1. Clonar el repositorio.
  2. Abrir en Android Studio.
  3. (Opcional) Abrir build.gradle (app) y cambiar la API key que se puede obtener siguiendo los pasos de la documentación de la API.
  4. Correr la app en un dispositivo o emulador.

Descripción

Utiliza las siguientes bibliotecas:

  • Retrofit2: Comunicación con la API.
  • Koin: Inyección de dependencias.
  • Glide: Carga de imágenes.
  • Room: Guardado de datos de la API para que la app pueda funcionar offline.
  • ViewModel + LiveData: Los ViewModels obtienen el estado (películas/series) de los repositorios y los emiten a la UI utilizando LiveData.
  • RxJava: Utilizado en los repositorios para obtener datos de la API o base de datos en un hilo secundario y emitir los resultados en el hilo principal.
  • View Binding: Para interactuar con las vistas más fácilmente.
  • JUnit y Mockito Kotlin: Para crear tests unitarios.

El proyecto está organizado en paquetes por feature:

  • main: Pantalla principal con listados de películas y series categorizados en Popular, Top Rated y Upcoming.
  • detail: Pantalla de detalle de película/serie.
  • search: Pantalla para buscar películas/series.

Capas de Aplicación

MoviesDatabase y MoviesDao pertenecen a la capa de Persistencia. Estos se utilizan para el funcionamiento de la app offline. Tienen métodos para guardar/obtener datos de una base de datos.

MainApi, DetailApi, SearchApi y Network pertenecen a la capa de Red. Estos se utilizan para el funcionamiento de la app online. Consumen datos de la API.

MainRepository, DetailRepository y SearchRepository pertenecen a la capa de Repositorio, internamente consume de la capa de Persistencia y Red.

Las clases dentro del paquete models podrían pertenecer a la capa de Negocio. Tienen los datos que se muestran en la app. Dado que no tienen mucha lógica de negocio podría decirse que en realidad pertenecen a la capa de Red y/o de Persistencia.

Las clases XXXXXActivity pertenecen a la capa de Vista. Estas clases tienen solo lógica de setear texto, animaciones, imágenes y componentes de vista en general. Reciben la interacción del usuario.

Las clases XXXXXAdapter pertenecen a la capa de Vista. Se utilizan para mostrar items en un listado.

Se usó la arquitectura MVVM con ViewModels y LiveData de Android Architecture Components, estos son el nexo entre Vista y Repositorio. Cuando el usuario interactúa con la vista, esta llama a un método del ViewModel, el cual consume del repositorio y setea los valores de los LiveData, estos últimos son observados por la Vista que actualiza de forma acorde.

Para inyectar dependencias se utilizó Koin, entonces en los paquetes di se pueden encontrar módulos que configuran las dependencias.

MoviesApplication representa a la app y es lo que primero se ejecuta. Inicializa Koin con los módulos.

Principio de Responsabilidad Única

Cada clase debe tener una solo objetivo o problema a resolver.

Por ejemplo, el MainRepositoryImpl tiene el objetivo de traer los datos, internamente obteniéndolos de una API o de una base de datos según si hay o no conexión a Internet. MainRepositoryImpl delega responsabilidades a:

  • NetworkImpl para el chequeo de la conexión.
  • La implementación de MainApi tiene el objetivo de traer los datos de la API.
  • La implementación de MoviesDao tiene el objetivo de guardar/traer los datos de la base de datos.

Si todo esto estuviese implementado dentro de la misma clase, no se estaría cumpliendo este principio.

Código Limpio

El proyecto fue desarrollado teniendo en cuenta estas características:

  • Fácil lectura para otros desarrolladores.
  • Fácil de extender o modificar.
  • Clases pequeñas, con pocos métodos, pocas líneas. Publicar solo los métodos necesarios. El resto debería ser privado.
  • Prestar atención al nombrado de clases, métodos y variables. Evitar nombres como "Manager", "Admin", etc.
  • Dado que se presta atención a los nombres, no sería necesario escribir comentarios, a menos que:
    • Sean TODOs/FIXMEs.
    • Se utilicen bibliotecas externas que tienen malos nombres que no podemos modificar.
    • Sea necesario aclarar alguna decisión técnica o de negocio.
  • Mantener formateo y consistencia entre clases. Si la clase A fue creada por el desarrollador A y la clase B fue creada por el desarrollador B, el desarrollador C al mirar ambas no debería poder identificar quien desarrolló qué clase.
  • Debe tener tests unitarios que den confianza para que cualquier desarrollador pueda modificar clases sin temor a romper funcionalidad existente crítica.
  • Inyectar dependencias: favoreciendo la responsabilidad única, alternativas de implementación y la facilidad de test.

Robert C. Martin (Uncle Bob) escribió el libro Clean Code: A Handbook of Agile Software Craftsmanship sobre este tema.

TODOs

  • Agregar más tests unitarios. Solo se crearon los principales, para demostrar el uso de JUnit y Mockito. Los tests que faltan de ViewModels y Repositorios serían muy similares a los existentes.

  • Obtener configuración primero antes de ejecutar el resto de los servicios. Esto serviría para agregar el base path a las imágenes. Ahora están hardcodeadas en la clase Show. Por ejemplo, se podría implementar usando RxJava y el operador zip, combinando el resultado de los observables de:

  • Manejar el caso de error cuando no carga la siguiente página.

  • UI/UX

About

Movies sample app

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages