|
| 1 | +# M2Utility Project Guidelines |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +M2Utility is a utility library designed to be used across a wide variety of projects. It provides flexible, extensible utilities that support a broad range of use cases. The project is structured as a multi-module Kotlin library with cross-platform (KMP) support. |
| 6 | + |
| 7 | +## Code Style |
| 8 | + |
| 9 | +### Kotlin Style Guide |
| 10 | + |
| 11 | +We follow the [official Kotlin style guide](https://kotlinlang.org/docs/coding-conventions.html) with the following additional requirements: |
| 12 | + |
| 13 | +- Use 4 spaces for indentation |
| 14 | +- Maximum line length is 120 characters |
| 15 | +- Use trailing commas in multi-line lists/arrays/parameters |
| 16 | +- Prefer named parameters for improved readability for functions with multiple parameters, especially when parameters share the same type |
| 17 | +- Always prefer explicit null handling; avoid `!!` (not null asserts) unless absolutely unavoidable |
| 18 | +- Use `require`, `requireNotNull`, `check`, `checkNotNull`, and `error` functions to enforce invariants early, and document these checks in KDoc comments |
| 19 | + |
| 20 | +### Documentation |
| 21 | + |
| 22 | +#### KDoc Comments |
| 23 | + |
| 24 | +- All public APIs must have KDoc comments |
| 25 | +- Use proper markdown formatting in KDoc |
| 26 | +- Include code examples where appropriate using markdown code blocks |
| 27 | +- Document all parameters, return values, and exceptions |
| 28 | + |
| 29 | +#### KDoc Tags |
| 30 | + |
| 31 | +- `@param` - Document all parameters with their purpose and constraints |
| 32 | +- `@property` - Document properties in classes, especially in data classes |
| 33 | +- `@return` - Document return values (not needed for functions returning `Unit`) |
| 34 | +- `@throws` - Document exceptions that the function explicitly throws |
| 35 | +- `@constructor` - Document class constructors when they have specific behavior |
| 36 | +- `@receiver` - Document extension function receivers to explain context |
| 37 | +- `@sample` - Use to reference sample code when available |
| 38 | +- `@deprecated` - Not supported by KDoc, use the `@Deprecated` annotation instead |
| 39 | + |
| 40 | +#### Markdown Style |
| 41 | + |
| 42 | +- Markdown headers should have a blank line above and below them |
| 43 | +- For Markdown headers use proper Title Casing (APA style) |
| 44 | +- For strong emphasis (bold) use `__text__` |
| 45 | +- For weak emphasis (italic) use `*text*` |
| 46 | +- Lists, code blocks, and quotes should have a blank line above and below them (except when they are part of a list) |
| 47 | +- Images should have a proper alt text and where possible a light and dark version as supported by GitHub |
| 48 | +- The Markdown dialect for md files is the GitHub flavor and for KDoc its the base Markdown dialect as supported by KDoc |
| 49 | +- Code blocks should always have a language specified where possible |
| 50 | +- For code references in Markdown either use a code block, inline code formatting (backticks), or for KDoc a KDoc style reference (example: `uses [SomeClass] to do things`) |
| 51 | + |
| 52 | +#### Deprecation |
| 53 | + |
| 54 | +For deprecated elements: |
| 55 | + |
| 56 | +- Add `@Deprecated` annotation with appropriate deprecation level and message |
| 57 | +- Include `replaceWith` parameter when possible to guide users to the new API |
| 58 | +- Document the reason for deprecation and migration path in KDoc |
| 59 | + |
| 60 | +Example: |
| 61 | + |
| 62 | +```kotlin |
| 63 | +/** |
| 64 | + * This method performs an operation that is now deprecated. |
| 65 | + */ |
| 66 | +@Deprecated( |
| 67 | + message = "Use newMethod() instead which provides better performance", |
| 68 | + replaceWith = ReplaceWith("newMethod()"), |
| 69 | + level = DeprecationLevel.WARNING |
| 70 | +) |
| 71 | +fun oldMethod() { |
| 72 | + // Implementation |
| 73 | + newMethod() // Delegate to new method when possible |
| 74 | +} |
| 75 | +``` |
| 76 | + |
| 77 | +### Changelog |
| 78 | + |
| 79 | +- Follow the [Keep a Changelog](https://keepachangelog.com/) format |
| 80 | +- Group changes under: Added, Changed, Deprecated, Removed, Fixed, Security, or Dependencies |
| 81 | +- Version numbers are a single number incremented by 1 for each release |
| 82 | +- Older releases are not maintained for this internal project |
| 83 | +- For new releases the current date should be included in the header |
| 84 | +- Change entries should be prefix with the correct module like `- __test:__ Added some function` |
| 85 | +- For breaking changes a `(Breaking)` should be suffixed to the change module prefix like `- __test (Breaking): Changed parameters of some function` |
| 86 | + |
| 87 | +### Module Documentation |
| 88 | + |
| 89 | +- Each module should have a comprehensive README.md |
| 90 | +- README files should be properly formatted for Dokka to generate documentation HTML for GitHub Pages |
| 91 | +- Include module purpose, main components, usage examples, and integration instructions for larger systems/functionality only |
| 92 | + |
| 93 | +## Code Quality |
| 94 | + |
| 95 | +### Static Analysis |
| 96 | + |
| 97 | +All code must pass: |
| 98 | + |
| 99 | +- Android lint checks |
| 100 | +- Detekt analysis (configuration in detekt-config.yml) |
| 101 | +- SonarQube analysis |
| 102 | + |
| 103 | +### Testing Requirements |
| 104 | + |
| 105 | +- All new code should have appropriate unit tests |
| 106 | +- Follow Behavior-Driven Testing principles with Given-When-Then structure |
| 107 | +- Test coverage should be maintained or improved with new code |
| 108 | +- Testing shared code should be prioritized over platform-specific tests where possible |
| 109 | +- Where relevant use a @ParameterizedTest |
| 110 | +- Bug fixes should have tests for them where possible |
| 111 | + |
| 112 | +### Testing Stack |
| 113 | + |
| 114 | +- JUnit 5 for test framework |
| 115 | +- MockK for mocking |
| 116 | +- EasyRandom for test data generation |
| 117 | +- Turbine for testing Flow |
| 118 | +- Custom utilities from test and test-android modules |
| 119 | + |
| 120 | +## Design Principles |
| 121 | + |
| 122 | +- **Flexibility**: Code should be adaptable to different use cases |
| 123 | +- **Extensibility**: Design for extension through inheritance or composition |
| 124 | +- **Reusability**: Components should be reusable across different projects |
| 125 | +- **Maintainability**: Code should be easy to understand and maintain |
| 126 | +- **Performance**: Consider performance implications, especially for utility functions |
| 127 | + |
| 128 | +## API Design and Maintenance |
| 129 | + |
| 130 | +### Public API Guidelines |
| 131 | + |
| 132 | +- For any public-facing API (including internal expect/actual in KMP), changes should: |
| 133 | + - Avoid breaking changes unless justified and properly documented |
| 134 | + - Consider using deprecation cycles (WARNING → ERROR → removal over releases) |
| 135 | +- For expect/actual declarations make sure to document platform specific implementations clearly. Also avoid leaking platform-specific concepts into common code |
| 136 | +- When APIs are only available on some targets explicitly mention it in KDoc |
| 137 | + |
| 138 | +### Coroutines |
| 139 | + |
| 140 | +- Use structured concurrency. Avoid GlobalScope (as per coroutine best practices) |
| 141 | +- Document coroutine context switches or expectations clearly in the KDocs |
| 142 | +- Prefer suspend functions and flows over callbacks |
| 143 | + |
| 144 | +## Versioning and Maintenance |
| 145 | + |
| 146 | +- Version numbers are incremented by 1 for each release |
| 147 | +- Only the latest version is maintained |
| 148 | +- Breaking changes should be clearly documented in the changelog |
| 149 | + |
| 150 | +## Dependencies Management |
| 151 | + |
| 152 | +### Dependency Guidelines |
| 153 | + |
| 154 | +- New dependencies should only be added when needed and only exposed using API in very rare exceptions |
| 155 | +- Use Kotlin stdlib and kotlinx libraries over alternatives where feasible |
| 156 | +- Dependencies that impact public API require extra scrutiny |
| 157 | + |
| 158 | +### Gradle Version Catalogue |
| 159 | + |
| 160 | +- New dependencies should be added using the Gradle version catalogue system |
| 161 | +- Use the standard `gradle/libs.versions.toml` file for version declarations |
| 162 | +- Follow the established pattern for declaring library versions and dependencies |
0 commit comments