-
Notifications
You must be signed in to change notification settings - Fork 0
Add lazy collection creation from closure and enhance collection methods. #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
ed9f364
feat: Add lazy collection creation from closure and enhance collectio…
gustavofreze 79f7fdb
refactor: Inline private toGenerator method in Equality
gustavofreze 7198460
refactor: Make EagerPipeline truly eager and final readonly
gustavofreze b5d1671
refactor: Inline private pipeTo method in Collection
gustavofreze 781c0d8
refactor: Remove PHPDoc from Order enum
gustavofreze 45ac250
docs: Add missing badges to README
gustavofreze ce4e4c0
fix: Correct indentation in EagerPipeline
gustavofreze 7ad50ac
fix: Correct indentation in Equality
gustavofreze 2117e24
fix: Correct indentation in Collection
gustavofreze 4804523
fix: Correct indentation in Order
gustavofreze 9e23977
fix: Remove duplicate class in EagerPipeline
gustavofreze 5ce2956
fix: Break long line in sort method to comply with 120-char limit
gustavofreze 3c5eadb
fix: Simplify EagerPipeline to fix phpstan analysis
gustavofreze adc1f15
docs: Update README with createLazyFromClosure and each void return
gustavofreze ee86c8f
fix: Refactor Filter and Rearrange classes for improved readability.
gustavofreze File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # Project | ||
|
|
||
| PHP microservices platform. Hexagonal architecture (ports & adapters), DDD, CQRS. | ||
|
|
||
| ## Rules | ||
|
|
||
| All coding standards, architecture, naming, testing, documentation, and OpenAPI conventions | ||
| are defined in `rules/`. Read the applicable rule files before generating any code or documentation. | ||
|
|
||
| ## Commands | ||
|
|
||
| - `make test` — run tests with coverage. | ||
| - `make mutation-test` — run mutation testing (Infection). | ||
| - `make review` — run lint. | ||
| - `make help` — list all available commands. | ||
|
|
||
| ## Post-change validation | ||
|
|
||
| After any code change, run `make review`, `make test`, and `make mutation-test`. | ||
| If any fails, iterate on the fix while respecting all project rules until all pass. | ||
| Never deliver code that breaks lint, tests, or leaves surviving mutants. | ||
|
|
||
| ## File formatting | ||
|
|
||
| Every file produced or modified must: | ||
|
|
||
| - Use **LF** line endings. Never CRLF. | ||
| - Have no trailing whitespace on any line. | ||
| - End with a single trailing newline. | ||
| - Have no consecutive blank lines (max one blank line between blocks). | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| --- | ||
| description: Standards for README files and all project documentation in PHP libraries. | ||
| paths: | ||
| - "**/*.md" | ||
| --- | ||
|
|
||
| # Documentation | ||
|
|
||
| ## README | ||
|
|
||
| 1. Include an anchor-linked table of contents. | ||
| 2. Start with a concise one-line description of what the library does. | ||
| 3. Include a **badges** section (license, build status, coverage, latest version, PHP version). | ||
| 4. Provide an **Overview** section explaining the problem the library solves and its design philosophy. | ||
| 5. **Installation** section: Composer command (`composer require vendor/package`). | ||
| 6. **How to use** section: complete, runnable code examples covering the primary use cases. Each example | ||
| includes a brief heading describing what it demonstrates. | ||
| 7. If the library exposes multiple entry points, strategies, or container types, document each with its own | ||
| subsection and example. | ||
| 8. **FAQ** section: include entries for common pitfalls, non-obvious behaviors, or design decisions that users | ||
| frequently ask about. Each entry is a numbered question as heading (e.g., `### 01. Why does X happen?`) | ||
| followed by a concise explanation. Only include entries that address real confusion points. | ||
| 9. **License** and **Contributing** sections at the end. | ||
| 10. Write strictly in American English. See `rules/code-style.md` American English section for spelling conventions. | ||
|
|
||
| ## Structured data | ||
|
|
||
| 1. When documenting constructors, factory methods, or configuration options with more than 3 parameters, | ||
| use tables with columns: Parameter, Type, Required, Description. | ||
| 2. Prefer tables to prose for any structured information. | ||
|
|
||
| ## Style | ||
|
|
||
| 1. Keep language concise and scannable. | ||
| 2. Never include placeholder content (`TODO`, `TBD`). | ||
| 3. Code examples must be syntactically correct and self-contained. | ||
| 4. Do not document `Internal/` classes or private API. Only document what consumers interact with. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| --- | ||
| description: Naming, ordering, inputs, security, and structural rules for all GitHub Actions workflow files. | ||
| paths: | ||
| - ".github/workflows/**/*.yml" | ||
| - ".github/workflows/**/*.yaml" | ||
| --- | ||
|
|
||
| # Workflows | ||
|
|
||
| Structural and stylistic rules for GitHub Actions workflow files. Refer to `shell-scripts.md` for Bash conventions used | ||
| inside `run:` steps, and to `terraforms.md` for Terraform conventions used in `terraform/`. | ||
|
|
||
| ## Pre-output checklist | ||
|
|
||
| Verify every item before producing any workflow YAML. If any item fails, revise before outputting. | ||
|
|
||
| 1. File name follows the convention: `ci-<runtime>.yml` for reusable CI, `cd-<purpose>.yml` for dispatch CD. | ||
| 2. `name` field follows the pattern `CI — <Context>` or `CD — <Context>`, using sentence case after the dash | ||
| (e.g., `CD — Run migration`, not `CD — Run Migration`). | ||
| 3. Reusable workflows use `workflow_call` trigger. CD workflows use `workflow_dispatch` trigger. | ||
| 4. Each workflow has a single responsibility. CI tests code. CD deploys it. Never combine both. | ||
| 5. Every input has a `description` field. Descriptions use American English and end with a period. | ||
| 6. Input names use `kebab-case`: `service-name`, `dry-run`, `skip-build`. | ||
| 7. Inputs are ordered: required first, then optional. Each group by **name length ascending**. | ||
| 8. Choice input options are in **alphabetical order**. | ||
| 9. `env`, `outputs`, and `with` entries are ordered by **key length ascending**. | ||
| 10. `permissions` keys are ordered by **key length ascending** (`contents` before `id-token`). | ||
| 11. Top-level workflow keys follow canonical order: `name`, `on`, `concurrency`, `permissions`, `env`, `jobs`. | ||
| 12. Job-level properties follow canonical order: `if`, `name`, `needs`, `uses`, `with`, `runs-on`, | ||
| `environment`, `timeout-minutes`, `strategy`, `outputs`, `permissions`, `env`, `steps`. | ||
| 13. All other YAML property names within a block are ordered by **name length ascending**. | ||
| 14. Jobs follow execution order: `load-config` → `lint` → `test` → `build` → `deploy`. | ||
| 15. Step names start with a verb and use sentence case: `Setup PHP`, `Run lint`, `Resolve image tag`. | ||
| 16. Runtime versions are resolved from the service repo's native dependency file (`composer.json`, `go.mod`, | ||
| `package.json`). No version is hardcoded in any workflow. | ||
| 17. Service-specific overrides live in a pipeline config file (e.g., `.pipeline.yml`) in the service repo, | ||
| not in the workflows repository. | ||
| 18. The `load-config` job reads the pipeline config file at runtime with safe fallback to defaults when absent. | ||
| 19. Top-level `permissions` defaults to read-only (`contents: read`). Jobs escalate only the permissions they | ||
| need. | ||
| 20. AWS authentication uses OIDC federation exclusively. Static access keys are forbidden. | ||
| 21. Secrets are passed via `secrets: inherit` from callers. No secret is hardcoded. | ||
| 22. Sensitive values fetched from SSM are masked with `::add-mask::` before assignment. | ||
| 23. Third-party actions are pinned to the latest available full commit SHA with a version comment: | ||
| `uses: aws-actions/configure-aws-credentials@<latest-sha> # v4.0.2`. Always verify the latest | ||
| version before generating a workflow. | ||
| 24. First-party actions (`actions/*`) are pinned to the latest major version tag available: | ||
| `actions/checkout@v4`. Always check for the most recent major version before generating a workflow. | ||
| 25. Production deployments require GitHub Environments protection rules (manual approval). | ||
| 26. Every job sets `timeout-minutes` to prevent indefinite hangs. CI jobs: 10–15 minutes. CD jobs: 20–30 | ||
| minutes. Adjust only with justification in a comment. | ||
| 27. CI workflows set `concurrency` with `group` scoped to the PR and `cancel-in-progress: true` to avoid | ||
| redundant runs. | ||
| 28. CD workflows set `concurrency` with `group` scoped to the environment and `cancel-in-progress: false` to | ||
| prevent interrupted deployments. | ||
| 29. CD workflows use `if: ${{ !cancelled() }}` to allow to deploy after optional build steps. | ||
| 30. Inline logic longer than 3 lines is extracted to a script in `scripts/ci/` or `scripts/cd/`. | ||
|
|
||
| ## Style | ||
|
|
||
| - All text (workflow names, step names, input descriptions, comments) uses American English with correct | ||
| spelling and punctuation. Sentences and descriptions end with a period. | ||
|
|
||
| ## Callers | ||
|
|
||
| - Callers trigger on `pull_request` targeting `main` only. No `push` trigger. | ||
| - Callers in service repos are static (~10 lines) and pass only `service-name` or `app-name`. | ||
| - Callers reference workflows with `@main` during development. Pin to a tag or SHA for production. | ||
|
|
||
| ## Image tagging | ||
|
|
||
| - CD deploy builds: `<environment>-sha-<short-hash>` + `latest`. | ||
|
|
||
| ## Migrations | ||
|
|
||
| - Migrations run **before** service deployment (schema first, code second). | ||
| - `cd-migrate.yml` supports `dry-run` mode (`flyway validate`) for pre-flight checks. | ||
| - Database credentials are fetched from SSM at runtime, never stored in workflow files. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| --- | ||
| description: Pre-output checklist, naming, typing, comparisons, and PHPDoc rules for all PHP files in libraries. | ||
| paths: | ||
| - "src/**/*.php" | ||
| - "tests/**/*.php" | ||
| --- | ||
|
|
||
| # Code style | ||
|
|
||
| Semantic code rules for all PHP files. Formatting rules (PSR-1, PSR-4, PSR-12, line length) are enforced by `phpcs.xml` | ||
| and are not repeated here. Refer to `rules/domain.md` for domain modeling rules. | ||
|
|
||
| ## Pre-output checklist | ||
|
|
||
| Verify every item before producing any PHP code. If any item fails, revise before outputting. | ||
|
|
||
| 1. `declare(strict_types=1)` is present. | ||
| 2. All classes are `final readonly` by default. Use `class` (without `final` or `readonly`) only when the class is | ||
| designed as an extension point for consumers (e.g., `Collection`, `ValueObject`). Use `final class` without | ||
| `readonly` only when the parent class is not readonly (e.g., extending a third-party abstract class). | ||
| 3. All parameters, return types, and properties have explicit types. | ||
| 4. Constructor property promotion is used. | ||
| 5. Named arguments are used at call sites for own code, tests, and third-party library methods (e.g., tiny-blocks). | ||
| Never use named arguments on native PHP functions (`array_map`, `in_array`, `preg_match`, `is_null`, | ||
| `iterator_to_array`, `sprintf`, `implode`, etc.) or PHPUnit assertions (`assertEquals`, `assertSame`, | ||
| `assertTrue`, `expectException`, etc.). | ||
| 6. No `else` or `else if` exists anywhere. Use early returns, polymorphism, or map dispatch instead. | ||
| 7. No abbreviations appear in identifiers. Use `$index` instead of `$i`, `$account` instead of `$acc`. | ||
| 8. No generic identifiers exist. Use domain-specific names instead: | ||
| `$data` → `$payload`, `$value` → `$totalAmount`, `$item` → `$element`, | ||
| `$info` → `$currencyDetails`, `$result` → `$conversionOutcome`. | ||
| 9. No raw arrays exist where a typed collection or value object is available. Use `tiny-blocks/collection` | ||
| (`Collection`, `Collectible`) instead of raw `array` for any list of domain objects. Raw arrays are acceptable | ||
| only for primitive configuration data, variadic pass-through, or interop at system boundaries. | ||
| 10. No private methods exist except private constructors for factory patterns. Inline trivial logic at the call site | ||
| or extract it to a collaborator or value object. | ||
| 11. Members are ordered: constants first, then constructor, then static methods, then instance methods. Within each | ||
| group, order by body size ascending (number of lines between `{` and `}`). Constants and enum cases, which have | ||
| no body, are ordered by name length ascending. | ||
| 12. Constructor parameters are ordered by parameter name length ascending (count the name only, without `$` or type), | ||
| except when parameters have an implicit semantic order (e.g., `$start/$end`, `$from/$to`, `$startAt/$endAt`), | ||
| which takes precedence. The same rule applies to named arguments at call sites. | ||
| Example: `$id` (2) → `$value` (5) → `$status` (6) → `$precision` (9). | ||
| 13. No O(N²) or worse complexity exists. | ||
| 14. No logic is duplicated across two or more places (DRY). | ||
| 15. No abstraction exists without real duplication or isolation need (KISS). | ||
| 16. All identifiers, comments, and documentation are written in American English. | ||
| 17. No justification comments exist (`// NOTE:`, `// REASON:`, etc.). Code speaks for itself. | ||
| 18. `// TODO: <reason>` is used when implementation is unknown, uncertain, or intentionally deferred. | ||
| Never leave silent gaps. | ||
| 19. All class references use `use` imports at the top of the file. Fully qualified names inline are prohibited. | ||
| 20. No dead or unused code exists. Remove unreferenced classes, methods, constants, and imports. | ||
| 21. Never create public methods, constants, or classes in `src/` solely to serve tests. If production code does not | ||
| need it, it does not exist. | ||
| 22. Always use the most current and clean syntax available in the target PHP version. Prefer match to switch, | ||
| first-class callables over `Closure::fromCallable()`, readonly promotion over manual assignment, enum methods | ||
| over external switch/if chains, named arguments over positional ambiguity (except where excluded by rule 5), | ||
| and `Collection::map` over foreach accumulation. | ||
| 23. No vertical alignment of types in parameter lists or property declarations. Use a single space between | ||
| type and variable name. Never pad with extra spaces to align columns: | ||
| `public OrderId $id` — not `public OrderId $id`. | ||
| 24. Opening brace `{` goes on the same line as the closing parenthesis `)` for constructors, methods, and | ||
| closures: `): ReturnType {` — not `): ReturnType\n {`. Parameters with default values go last. | ||
|
|
||
| ## Casing conventions | ||
|
|
||
| - Internal code (variables, methods, classes): **`camelCase`**. | ||
| - Constants and enum-backed values when representing codes: **`SCREAMING_SNAKE_CASE`**. | ||
|
|
||
| ## Naming | ||
|
|
||
| - Names describe **what** in domain terms, not **how** technically: `$monthlyRevenue` instead of `$calculatedValue`. | ||
| - Generic technical verbs (`process`, `handle`, `execute`, `mark`, `enforce`, `manage`, `ensure`, `validate`, | ||
| `check`, `verify`, `assert`, `transform`, `parse`, `compute`, `sanitize`, `normalize`) **should be avoided**. | ||
| Prefer names that describe the domain operation. | ||
| - Booleans use predicate form: `isActive`, `hasPermission`, `wasProcessed`. | ||
| - Collections are always plural: `$orders`, `$lines`. | ||
| - Methods returning bool use prefixes: `is`, `has`, `can`, `was`, `should`. | ||
|
|
||
| ## Comparisons | ||
|
|
||
| 1. Null checks: use `is_null($variable)`, never `$variable === null`. | ||
| 2. Empty string checks on typed `string` parameters: use `$variable === ''`. Avoid `empty()` on typed strings | ||
| because `empty('0')` returns `true`. | ||
| 3. Mixed or untyped checks (value may be `null`, empty string, `0`, or `false`): use `empty($variable)`. | ||
|
|
||
| ## American English | ||
|
|
||
| All identifiers, enum values, comments, and error codes use American English spelling: | ||
| `canceled` (not `cancelled`), `organization` (not `organisation`), `initialize` (not `initialise`), | ||
| `behavior` (not `behaviour`), `modeling` (not `modelling`), `labeled` (not `labelled`), | ||
| `fulfill` (not `fulfil`), `color` (not `colour`). | ||
|
|
||
| ## PHPDoc | ||
|
|
||
| - PHPDoc is restricted to interfaces only, documenting obligations and `@throws`. | ||
| - Never add PHPDoc to concrete classes. | ||
|
|
||
| ## Collection usage | ||
|
|
||
| When a property or parameter is `Collectible`, use its fluent API. Never break out to raw array functions. | ||
|
|
||
| **Prohibited — `array_map` + `iterator_to_array` on a Collectible:** | ||
|
|
||
| ```php | ||
| $names = array_map( | ||
| static fn(Element $element): string => $element->name(), | ||
| iterator_to_array($collection) | ||
| ); | ||
| ``` | ||
|
|
||
| **Correct — fluent chain with `map()` + `toArray()`:** | ||
|
|
||
| ```php | ||
| $names = $collection | ||
| ->map(transformations: static fn(Element $element): string => $element->name()) | ||
| ->toArray(keyPreservation: KeyPreservation::DISCARD); | ||
| ``` | ||
|
|
||
| The same applies to `filter()`, `reduce()`, `each()`, and all other `Collectible` operations. Chain them | ||
| fluently. Never materialize with `iterator_to_array` to then pass into a raw `array_*` function. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| --- | ||
| description: Domain modeling rules for PHP libraries — folder structure, naming, value objects, exceptions, enums, and SOLID. | ||
| paths: | ||
| - "src/**/*.php" | ||
| --- | ||
|
|
||
| # Domain modeling | ||
|
|
||
| Libraries are self-contained packages. The core has no dependency on frameworks, databases, or I/O. | ||
| Refer to `rules/code-style.md` for the pre-output checklist applied to all PHP code. | ||
|
|
||
| ## Folder structure | ||
|
|
||
| ``` | ||
| src/ | ||
| ├── <PublicInterface>.php # Primary contract for consumers | ||
| ├── <Implementation>.php # Main implementation or extension point | ||
| ├── <Enum>.php # Public enum | ||
| ├── Contracts/ # Interfaces for data returned to consumers | ||
| ├── Internal/ # Implementation details (not part of public API) | ||
| │ ├── <Collaborator>.php | ||
| │ └── Exceptions/ # Internal exception classes | ||
| ├── <Feature>/ # Feature-specific subdirectory when needed | ||
| └── Exceptions/ # Public exception classes (when part of the API) | ||
| ``` | ||
|
|
||
| **Public API boundary:** Only interfaces, extension points, enums, and thin orchestration classes live at the | ||
| `src/` root. These classes define the contract consumers interact with and delegate all real work to collaborators | ||
| inside `src/Internal/`. If a class contains substantial logic (algorithms, state machines, I/O), it belongs in | ||
| `Internal/`, not at the root. | ||
|
|
||
| The `Internal/` namespace signals classes that are implementation details. Consumers must not depend on them. | ||
| Never use `Entities/`, `ValueObjects/`, `Enums/`, or `Domain/` as folder names. | ||
|
|
||
| ## Nomenclature | ||
|
|
||
| 1. Every class, property, method, and exception name reflects the **domain concept** the library represents. | ||
| A math library uses `Precision`, `RoundingMode`; a money library uses `Currency`, `Amount`; a collection | ||
| library uses `Collectible`, `Order`. | ||
| 2. Never use generic technical names: `Manager`, `Helper`, `Processor`, `Data`, `Info`, `Utils`, | ||
| `Item`, `Record`, `Entity`, `Exception`, `Ensure`, `Validate`, `Check`, `Verify`, | ||
| `Assert`, `Transform`, `Parse`, `Compute`, `Sanitize`, or `Normalize` as class suffixes or prefixes. | ||
| 3. Name classes after what they represent: `Money`, `Color`, `Pipeline` — not after what they do technically. | ||
| 4. Name methods after the operation in domain terms: `add()`, `convertTo()`, `splitAt()` — not `process()`, | ||
| `handle()`, `execute()`, `manage()`, `ensure()`, `validate()`, `check()`, `verify()`, `assert()`, | ||
| `transform()`, `parse()`, `compute()`, `sanitize()`, or `normalize()`. | ||
|
|
||
| ## Value objects | ||
|
|
||
| 1. Are immutable: no setters, no mutation after construction. Operations return new instances. | ||
| 2. Compare by value, not by reference. | ||
| 3. Validate invariants in the constructor and throw on invalid input. | ||
| 4. Have no identity field. | ||
| 5. Use static factory methods (e.g., `from`, `of`, `zero`) with a private constructor when multiple creation | ||
| paths exist. | ||
|
|
||
| ## Exceptions | ||
|
|
||
| 1. Extend native PHP exceptions (`DomainException`, `InvalidArgumentException`, `OverflowException`, etc.). | ||
| 2. Are pure: no formatted `code`/`message` for HTTP responses. | ||
| 3. Signal invariant violations only. | ||
| 4. Name after the invariant violated, never after the technical type: | ||
| `PrecisionOutOfRange` — not `InvalidPrecisionException`. | ||
| `CurrencyMismatch` — not `BadCurrencyException`. | ||
| `ContainerWaitTimeout` — not `TimeoutException`. | ||
| 5. Create the exception class directly with the invariant name and the appropriate native parent. The exception | ||
| is dedicated by definition when its name describes the specific invariant it guards. | ||
|
|
||
| ## Enums | ||
|
|
||
| 1. Are PHP backed enums. | ||
| 2. Include domain-meaningful methods when needed (e.g., `Order::ASCENDING_KEY`). | ||
|
|
||
| ## Extension points | ||
|
|
||
| 1. When a class is designed to be extended by consumers (e.g., `Collection`, `ValueObject`), it uses `class` | ||
| instead of `final readonly class`. All other classes use `final readonly class`. | ||
| 2. Extension point classes use a private constructor with static factory methods (`createFrom`, `createFromEmpty`) | ||
| as the only creation path. | ||
| 3. Internal state is injected via the constructor and stored in a `private readonly` property. | ||
|
|
||
| ## Principles | ||
|
|
||
| - **Immutability**: all models and value objects adopt immutability. Operations return new instances. | ||
| - **Zero dependencies**: the library's core has no dependency on frameworks, databases, or I/O. | ||
| - **Small surface area**: expose only what consumers need. Hide implementation in `Internal/`. | ||
|
|
||
| ## SOLID reference | ||
|
|
||
| | Principle | Failure signal | | ||
| |---------------------------|---------------------------------------------| | ||
| | S — Single responsibility | Class does two unrelated things | | ||
| | O — Open/closed | Adding a feature requires editing internals | | ||
| | L — Liskov substitution | Subclass throws on parent method | | ||
| | I — Interface segregation | Interface has unused methods | | ||
| | D — Dependency inversion | Constructor uses `new ConcreteClass()` | |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.