Skip to content

47tibo/weatherPanameAndroid

Repository files navigation

Weather Paname 🇫🇷 ⛅

Features

Weather in Paris in a blink ! Hourly detail for the current day, by segment on the next 7 days. There is more ! You will discover :

  • temperature in celsius
  • wind direction
  • blowing power

Say bye to bad surprises when leaving the subway (or riding your bike).

Technical specs

Code convention

Ktlint via kotlinter.

Personal choices :

  • for packages' names I use camel case (not best practice, I wont do it on next projects).
  • for functions arguments, the default is positional. Indeed Android Studio gives enough intel on arguments. I use named arguments only for disambiguation, when optional arguments are in the function's signature. The exception is for Composable functions, where named arguments are mandatory.
  • for abbreviations, I use capitalize case, not screaming case. Eg : Dto, not DTO
  • tests files (unit and e2e) use Test in their names : as a prefix for stubs and as suffix for tests classes
  • to avoid conflicts with Compose classes, I use the Main prefix (e.g MainNavHost)
  • for enum classes, I use capitalize case, not screaming case

In version catalog, variables naming is inspired by Now In Android Google app. Variables' names format depend on type :

  • [versions] : camelcase, the shorter the better, eg agp, ksp. Sometimes prefixing can be necessary, eg androidxEspresso
  • [libraries] : kebabcase, merge groupId segments with nameId ones. Eg { group = "androidx.compose.material3", name = "material3" } becomes androidx-compose-material3. If groupId's segments give no information, they should be discarded, eg { group = "com.google.dagger", name = "hilt-android-testing", version.ref = "hilt" } becomes hilt-android-testing. Examples of segments with low semantics : com, google, io, dagger, jetbrains
  • [plugins] : kebabcase, based on the groupId, the shorter the better, eg ksp, hilt. Same names than in [versions] can be used. Prefix can be used for disambiguation, eg android-application

Weather data API

Weather data for Paris is retrieved from OpenWeather. API is autogenerated with OpenAPI generator, with all the configuration and template in weather subproject, under /open_weather_api.

The OpenWeather.yaml file is created by transforming a Postman collection containing an OpenWeather JSON response to an OpenAPI scheme. This, thanks to this tool.

Once the proper scheme is created, in order to generate the API, simply run :

./gradlew openApiGenerate

Note : The generated DTO fields are all nullable. Instead of a painful configuration of OpenAPI's templates, I've choose to use the not null assertion operator in WeatherAssembler.

Third party artifacts and integration

  • Compose Navigation
  • Hilt for DI
  • Retrofit for network requests
  • Ktlint for linting, runs on pre-push
  • Kover for code coverage runs on Bitrise (release flavor)
  • Compose Preview Screenshot Testing, for weekly-weather-ui component. Run :
./gradlew :weekly-weather-ui:validateScreenshotTest

Application architecture

Based on Robert C. Martin's Clean Architecture, more precisely the package by components packaging strategy, proposed by Simon Brown in chapter 24.

The architecture diagram is components_architecture.drawio file, at the root of this project. This file has to be open with DrawIO tool (free and really cool).

Separation between abstraction and concrete implementation (especially for remote data sources) is handled via Hilt Modules bindings.

Specific concepts of Repository, Gateway, DTO & Assembler are extract from Eric Evans & Martin Fowler books Domain Driven Design & PEAA.

Data flows contain Kotlin's Result, which are created on the lowest level (in architectural term), ie in the network layer implementation. This in order to wrap exceptions as soon as possible, as recommended in this Kotlin Conf talk.

All the following components are packaged as gradle subprojects.

Application components

They strictly follows encapsulation and dependency rule, using interfaces to define contracts (and for DIP, when needed). Libraries are encapsulated using internal modifier.

They are under the com.tibo47.weatherPaname package.

app component

This component is at the lower level in the architecture. It bootstrap the main activity & application. It connects ui component (see bellow) via navigation. Its android test target provides e2e tests.

weather component

This component is an android library. It contains all the business and data-providing logic to retrieve and expose data about Paris' weather. It only exposes OpenWeather Retrofit API & uses cases.

weekly-weather-ui component

This component is an android library. It contains ui components to display the main screen for the current weather.

External components

http-client component

Under com.tibo47.httpClient package.

Exposes a Retrofit factory with :

  • KotlinX serialization Json
  • HttpLoggingInterceptor

android-platform component

Under com.tibo47.androidPlatform package.

It contains a preconfigured material design 3 theme and generic, non business oriented, ui components.

About

weatherPaname android 🤖 app

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published