{"id":21039681,"url":"https://github.com/programadorthi/chuck-norris-facts","last_synced_at":"2025-03-13T21:18:52.370Z","repository":{"id":96415408,"uuid":"216199119","full_name":"programadorthi/chuck-norris-facts","owner":"programadorthi","description":"A project that consumes Chuck Norris Jokes API","archived":false,"fork":false,"pushed_at":"2020-11-03T17:33:54.000Z","size":416,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-20T16:44:10.206Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/programadorthi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-10-19T11:57:53.000Z","updated_at":"2023-05-12T14:13:07.000Z","dependencies_parsed_at":null,"dependency_job_id":"d2221378-6e23-4b3e-a39f-c6d471ccbf1c","html_url":"https://github.com/programadorthi/chuck-norris-facts","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fchuck-norris-facts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fchuck-norris-facts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fchuck-norris-facts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fchuck-norris-facts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/programadorthi","download_url":"https://codeload.github.com/programadorthi/chuck-norris-facts/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243482942,"owners_count":20297908,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T13:43:26.041Z","updated_at":"2025-03-13T21:18:52.336Z","avatar_url":"https://github.com/programadorthi.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Configurações mínimas\n\n- Gradle 5.4.1;\n- Android Studio 3.5.1 (mesmo não tendo suporte total a Kotlin DSL);\n- File -\u003e Settings -\u003e Editor -\u003e Code Style -\u003e\n\t- Kotlin -\u003e\n\t\t- Set from... -\u003e Predefined Style -\u003e Kotlin Style guide\n\t\t- Imports -\u003e\n\t\t\t- Top-level Symbols -\u003e Use single name import\n\t\t\t- Java Statics and Enum members -\u003e Use single name import\n\t\t\t- Packages to Use import with '*' -\u003e Uncheck all checkbox\n\t- XML -\u003e\n\t\t- Set from... -\u003e Predefined Style -\u003e Android\n\n# Projeto com Kotlin DSL\n\nKotlin DSL oferece um mecanismo mais amigável para configurações de projetos Gradle, além de outros suportes como:\n\n- A statically typed and a type-safe DSL (inherited from Kotlin);\n- An enhanced IDE editing experience (inherited from Kotlin);\n- Interoperability with existing scripts (as a JVM language);\n- Maximum readability (as any DSL);\n- Consistency and super power (by using the same language across the project — source code and configuration 💯 Kotlin);\n\nReferências: [Migrating Android build scripts from Groovy to Kotlin DSL], [Kotlin + buildSrc for Better Gradle Dependency Management]\n\n## Problemas com Gradle DSL\n\n-   Very poor IDE assistant when writing a Groovy DSL script\n-   Performance issues*\n-   Errors at build runtime instead of compile time\n-   Painful build script debugging experience\n-   Refactoring is a pain in 🤬\n\nReferência: [Migrating Android build scripts from Groovy to Kotlin DSL]\n\n# Simulando Build de CI\n\nAs configuraçoes de CI variam de serviço para serviço. Esse projeto tem apenas um script que simula como seria o build de CI. As chamadas presentes no script funciona em qualquer ferramenta de CI. Para simular basta executar o script:\n\n```\n./any-ci-build.sh\n```\n\n\u003e Na execução serão realizados os seguintes passos:\n  - Validação com o ktlint\n  - Validação com o detekt\n  - Execução de todos os testes existentes no projeto\n  - Build do projeto versão desenvolvimento\n\n# Estrutura do projeto\n\nO projeto está estruturado para garantir uma boa escalabilidade e fornecer suporte futuro para recursos como [Dynamic Delivery] que ajudam a reduzir o tamanho do app e entregar features sobre demanda. Para facilitar encontrar as coisas, projetos que são features tem sufixos `-ui`, `-domain` e `-data` e projetos que tem coisas compartilháveis para outros projetos tem o prefixo `shared-`. Com isso, outros projetos podem escolher o que utilizar referenciando coisas específicas e melhorando o build do projeto.\n\n\u003e **Aviso**: esse projeto não nasceu do zero. Algumas das melhores práticas, estruturas e comportamentos foram obtidas combinando outras referências da internet. Todas elas serão referenciadas durante toda a documentação.\n\u003e \"Na natureza nada se cria, nada se perde, tudo se transforma.\" - **Antoine Lavoisier**\n\n## buildSrc\n\n**Projeto com as configurações de todos os outros projetos**.\n*A estrutura de buildSrc foi baseada no [Norris] com algumas modificações*.\n\n - **configs** - Pacote com arquivos que contém configurações de projeto Android, Kotlin, etc.\n    - `AndroidConfig.kt` - Configurações para projetos Android. Ver [Configure your build].\n    - `FlavorConfig.kt` - Configurações de product flavors. Ver [Configure build variants].\n    - `KotlinConfig.kt` - Configurações do Kotlin como versão e JVM target.\n    - `ProguardConfig.kt` - Configurações de proguard. Usada para aplicar arquivos proguard nos projetos.\n    - `SigningConfig.kt` - Configurações de assinatura usadas para gerar a versão de produção do aplicativo.\n - **dependencies** - Pacote com as dependências e configurações para desenvolvimento e testes.\n    - `Libraries.kt` - Contém as dependências de desenvolvimento e testes usadas no projeto.\n    - `UnitTestDependencies.kt` - Classe helper que ajudar a adicionar dependências de testes unitários nos módulos usando uma lista pré-definida de dependências.\n    - `InstrumentationTestsDependencies.kt` - Classe helper que ajudar a adicionar dependências de testes instrumentados nos módulos Android usando uma lista pré-definida de dependências.\n - **modules** - Pacotes com os nomes dos módulos existentes no projeto.\n    - `ProjectModules.kt` - Contém os nomes dos módulos existentes no projeto. Todas vez que um módulo for adicionado ao projeto é necessário registrar nesse object. 😛\n    - `LibraryType.kt` - Uma sealed class usada para carregar configurações específicas de cada módulo.\n    - `LibraryModule.kt` - Classe helper que carrega as configurações do módulo que estão em arquivos `.gradle` com base no tipo informado pela `LibraryType`.\n - `BuildPlugins.kt` - Arquivos com os plugins que determinam o tipo de cada módulo e os que são usados para desenvolvimento e testes.\n - `Version.kt` - Uma data class usada para auxiliar na geração do número de versão.\n - `Versioning.kt` - Contém a lógica para versionamento do app. Usada para gerar o `versionCode` e `versionName` do aplicativo.\n\n## shared-domain\n\n**Projeto Kotlin com conteúdos de domínio compartilhados por todos os outros módulos**.\n*Geralmente todos os outros módulos domain, data e UI terão referência direta/indireta para esse módulo*.\n\n## shared-network\n\n**Projeto Kotlin com recursos para consumir API. A ideia é centralizar recursos que são necessários para consumir API Rest**.\n*Apenas módulos que consomem API ou configuração de DI terão referência para esse projeto*.\n\n# Tecnologias\n  - **Kotlin Serialization** - Usado para converter dados JSON. Com ela evita o Reflection do Gson e o generate adapter do Moshi.\n  - **RxJava** - Poderia ser coroutines, mas quis manter a tecnologia descrita na última entrevista.\n  - **Retrofit** - Esse dispensa explicações, pois é a lib mais utilizada para consumir APIs no Android.\n  - **AndroidX** - Deixa o projeto mais clean baixando apenas dependências necessárias.\n  - **ViewModel** - Ajuda a manter os dados após a Activity ser destruída, mesmo não tendo rotação de tela.\n  - **LiveData** - Uma alternativa para emitir dados no padrão Observer. Trabalha bem com o clico de vida do Android, emitindo valores apenas quando a Activity/Fragment está disponível para receber.\n  - **Material** Design Components - Componentes do Android com estilos do Material Design. Ajudam na criação de layout como Cards e Chips.\n  - **Koin** - Um framework para ajudar na injeção de dependências. Poderia ser Dagger 2, Kodein, etc...\n  - **assertJ** - Framework de testes que fornece informações significativas quando os testes falham\n  - **Robolectric** - Ajuda na criação de testes de UI que se comportam como testes unitários. É mais rápido na execução e validação dos testes, diminuindo o tempo de execução no trabalho local e na execução de um build no CI.\n\n# Explicando alguns comportamentos\n\n## shared-network\n  - **NetworkingError** - Uma sealed class com alguns tipos de erro que podem acontecer durante uma operação de chamada de API. São utilizadas para representar erros que aconteceram na camada de data quando tentava realizar uma chamada de API.\n  - **DefaultNetworkManager** - Executa todo tipo de chamada de API e mapeia os cenários de erro quando encontrado algum para o **NetworkingError**. Todas as suas operações só são executadas após checagem de conexão com a internet.\n\n## facts-data\n  - **FactsMapper** - Toda chamada de API que retorna dados para serem consumidos pelo app deveria ter um Mapper. A responsabilidade do Mapper é garantir que campos obrigatórios para funcionamento da aplicação estejam sendo retornados pela API. Caso algum desses campos esteja faltando, um **NetworkingError.EssentialParamMissing** deveria ser lançando informando quais campos estão faltando e em qual resposta da API. Assim, basta logar a exceção em algum sistema de crash para monitorar o problema e reportar ao backend. Com isso, garante-se que o app sempre vai funcionar mesmo quando algum dos dados obrigatórios não foi retornado.\n  - **classes raw** - São classes com configurações de serialização. Os campos obrigatórios vão para `const val` em `companion object`, pois assim é possível logar o nome do campo no Mapper.\n  - **FactsRepositoryImpl** - Como existe mais de uma fonte de dados, para o Domain só deveria existir uma e é por isso que existe esse repository para centralizar os dados que podem ser local ou remoto na hora de retornar para a Domain.\n\n## facts-domain\n  - **FactsBusiness** - Uma sealed class com todos os tipos de validação que pode acontecer. Como a View e o ViewModel não deveriam e não devem realizar validações, todos os status de validação de são representados por classes como essas.\n  - **FactsUseCaseImpl** - Aplica validações para os dados obtidos pela camada de apresentação. Também, em caso de validado com sucesso, pode solicitar a camada de data que execute alguma ação.\n\n## facts-ui\n  - **classes ViewModel** - Gerenciam os dados apresentados na UI. Seu comportamento é apenas obter informações e repassar para a UI quando a mesma estiver disponível. Também mapeia o sucesso ou erro para o tipo `Result` facilitando para a UI receber a informação unificada. PS: **Não há necessidade de usar o observeOn aqui, pois toda operação já executa no Scheduler de IO e, quando usado o postValue do MutableLiveData, ele já envia o valor na Main Thread.**\n  - **app module** - Algumas abstrações foram implementadas dentro do módulo de aplicação. Indenpendente da abordagem, como a que foi aplicada no projeto com `library` ou um futuramete `dynamic feature`, isso facilita compartilhar entre módulos os comportametos, já que são instanciados via dependency injection.\n  - **MainActivity** - Está usando um `Handler` apenas para simular uma Splash Screen que realiza uma operação de checagem de informação, como por exemplo, verificar se o usuário está logado.\n\n\n\n\n\n[Migrating Android build scripts from Groovy to Kotlin DSL]: \u003chttps://proandroiddev.com/migrating-android-build-scripts-from-groovy-to-kotlin-dsl-f8db79dd6737\u003e\n\n[Kotlin + buildSrc for Better Gradle Dependency Management]: \u003chttps://handstandsam.com/2018/02/11/kotlin-buildsrc-for-better-gradle-dependency-management/\u003e\n\n[Norris]: \u003chttps://github.com/dotanuki-labs/norris\u003e\n\n[Configure your build]: \u003chttps://developer.android.com/studio/build\u003e\n\n[Configure build variants]: \u003chttps://developer.android.com/studio/build/build-variants\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogramadorthi%2Fchuck-norris-facts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprogramadorthi%2Fchuck-norris-facts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogramadorthi%2Fchuck-norris-facts/lists"}