Skip to content

Commit 1c28488

Browse files
committed
refactor: update command architecture and documentation for improved clarity and dependency injection
Signed-off-by: Felipe Sayão Lobato Abreu <github@mentordosnerds.com>
1 parent 514693d commit 1c28488

7 files changed

Lines changed: 68 additions & 29 deletions

File tree

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ composer dev-tools gitattributes
8383
# Generates a LICENSE file from composer.json license information
8484
composer dev-tools license
8585

86+
# Copies packaged or local resources into the consumer repository
87+
composer dev-tools copy-resource --source resources/docblock --target .docheader
88+
89+
# Installs Fast Forward Git hooks
90+
composer dev-tools git-hooks
91+
92+
# Updates the composer.json file to match the packaged schema
93+
composer dev-tools update-composer-json --force
94+
8695
# Installs and synchronizes dev-tools scripts, GitHub Actions workflows,
8796
# .editorconfig, .gitignore rules, packaged skills, and the repository wiki
8897
# submodule in .github/wiki
@@ -119,6 +128,17 @@ keeps the same command vocabulary when you prefer running tools directly from
119128
`vendor/bin/dev-tools`. The consumer sync flow also refreshes `.agents/skills`
120129
so agents can discover the packaged skills shipped with this repository.
121130

131+
## 🏗️ Architecture
132+
133+
Commands no longer extend a shared abstract base. Each command is self-contained
134+
and receives its dependencies through constructor injection, following
135+
the :abbr:`DI` pattern. The ``ProcessBuilder`` and ``ProcessQueue`` classes
136+
provide a fluent API for constructing and executing system processes in sequence.
137+
138+
- ``ProcessBuilderInterface`` - Builds process commands with arguments
139+
- ``ProcessQueueInterface`` - Manages and executes process queues
140+
- ``FilesystemInterface`` - Abstracts filesystem operations
141+
122142
## 🤝 Contributing
123143

124144
Run `composer dev-tools` before opening a pull request. If you change public

docs/api/commands.rst

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
11
Command Classes
22
===============
33

4-
All public CLI commands extend
5-
``FastForward\DevTools\Console\Command\AbstractCommand``, which provides path
6-
resolution, configuration fallback, PSR-4 lookup, and child-command dispatch.
4+
All public CLI commands extend ``Composer\Command\BaseCommand`` and receive
5+
dependencies through constructor injection. The architecture uses
6+
``ProcessBuilder`` and ``ProcessQueue`` for fluent process management.
77

88
.. list-table::
99
:header-rows: 1
1010

1111
* - Class
1212
- CLI command
1313
- Responsibility
14-
* - ``FastForward\DevTools\Console\Command\AbstractCommand``
15-
- n/a
16-
- Shared helpers for path resolution, packaged fallback files, PSR-4
17-
discovery, and subcommand execution.
1814
* - ``FastForward\DevTools\Console\Command\StandardsCommand``
1915
- ``standards``
2016
- Runs the full quality pipeline.
@@ -52,6 +48,18 @@ resolution, configuration fallback, PSR-4 lookup, and child-command dispatch.
5248
* - ``FastForward\DevTools\Console\Command\GitIgnoreCommand``
5349
- ``gitignore``
5450
- Merges and synchronizes .gitignore files.
51+
* - ``FastForward\DevTools\Console\Command\GitAttributesCommand``
52+
- ``gitattributes``
53+
- Manages export-ignore rules in .gitattributes.
5554
* - ``FastForward\DevTools\Console\Command\LicenseCommand``
5655
- ``license``
5756
- Generates a LICENSE file from composer.json license information.
57+
* - ``FastForward\DevTools\Console\Command\CopyResourceCommand``
58+
- ``copy-resource``
59+
- Copies packaged or local resources into the consumer repository.
60+
* - ``FastForward\DevTools\Console\Command\GitHooksCommand``
61+
- ``git-hooks``
62+
- Installs Fast Forward Git hooks.
63+
* - ``FastForward\DevTools\Console\Command\UpdateComposerJsonCommand``
64+
- ``update-composer-json``
65+
- Updates the composer.json file to match the packaged schema.

docs/configuration/overriding-defaults.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ without forking the whole package.
77
Resolution Order
88
----------------
99

10-
``FastForward\DevTools\Console\Command\AbstractCommand::getConfigFile()`` resolves
11-
configuration in this order:
10+
Commands use ``Symfony\Component\Config\FileLocatorInterface`` to locate
11+
configuration files. The locator resolves configuration in this order:
1212

1313
1. Check whether the file exists in the current working directory.
1414
2. Use the local file when it exists.
1515
3. Otherwise fall back to the packaged file inside ``fast-forward/dev-tools``.
1616

17+
This behavior is consistent across all commands through the DI container
18+
and ``FileLocatorInterface``.
19+
1720
Commands and Their Configuration Files
1821
--------------------------------------
1922

docs/internals/architecture.rst

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Architecture and Command Lifecycle
2-
==================================
2+
=================================
33

44
The package has two connected execution models: local command execution and
55
consumer repository synchronization.
@@ -14,9 +14,8 @@ Local Command Lifecycle
1414
``FastForward\DevTools\Composer\Capability\DevToolsCommandProvider``.
1515
4. ``standards`` is used as the default command when no explicit command name
1616
is given.
17-
5. Individual commands resolve local configuration first and packaged
18-
fallbacks second through
19-
``FastForward\DevTools\Console\Command\AbstractCommand::getConfigFile()``.
17+
5. Commands receive dependencies through constructor injection from
18+
``DevToolsServiceProvider``.
2019

2120
Consumer Synchronization Lifecycle
2221
----------------------------------
@@ -39,24 +38,33 @@ Documentation Pipeline
3938
----------------------
4039

4140
1. ``FastForward\DevTools\Console\Command\DocsCommand`` reads PSR-4 paths from
42-
``composer.json``.
43-
2. It generates a temporary ``phpdocumentor.xml`` file in
44-
``tmp/cache/phpdoc``.
41+
``composer.json`` via ``ComposerJsonInterface``.
42+
2. It generates a temporary ``phpdocumentor.xml`` file in the configured cache
43+
directory.
4544
3. phpDocumentor builds API pages from those PSR-4 paths.
4645
4. phpDocumentor also builds the guide from the selected ``docs/`` source
4746
directory.
4847
5. ``FastForward\DevTools\Console\Command\ReportsCommand`` combines that
4948
documentation build with PHPUnit coverage generation.
5049

51-
Key Abstraction
52-
---------------
50+
Dependency Injection
51+
--------------------
52+
53+
Commands receive their dependencies through constructor injection provided by
54+
``DevToolsServiceProvider``.
5355

54-
``FastForward\DevTools\Console\Command\AbstractCommand`` is the main shared layer. It
55-
centralizes:
56+
.. list-table::
57+
:header-rows: 1
5658

57-
- current working directory detection;
58-
- absolute path resolution;
59-
- local-versus-packaged config lookup;
60-
- command-to-command dispatch inside the same application;
61-
- access to Composer package metadata such as PSR-4 namespaces and project
62-
description.
59+
* - Interface
60+
- Purpose
61+
* - ``FastForward\DevTools\Process\ProcessBuilderInterface``
62+
- Builds process commands with a fluent API for arguments.
63+
* - ``FastForward\DevTools\Process\ProcessQueueInterface``
64+
- Queues and executes multiple processes in sequence.
65+
* - ``FastForward\DevTools\Filesystem\FilesystemInterface``
66+
- Abstracts filesystem operations.
67+
* - ``FastForward\DevTools\Composer\Json\ComposerJsonInterface``
68+
- Reads and validates ``composer.json`` metadata.
69+
* - ``Symfony\Component\Config\FileLocatorInterface``
70+
- Locates configuration files.

src/Console/Command/SyncCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7777
{
7878
$output->writeln('<info>Starting dev-tools synchronization...</info>');
7979

80-
$this->queueDevToolsCommand(['composer-json:update']);
80+
$this->queueDevToolsCommand(['update-composer-json']);
8181
$this->queueDevToolsCommand(
8282
[
8383
'copy-resource',

src/Console/Command/UpdateComposerJsonCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
* Updates composer.json with the Fast Forward dev-tools integration metadata.
3737
*/
3838
#[AsCommand(
39-
name: 'composer-json:update',
39+
name: 'update-composer-json',
4040
description: 'Updates composer.json with Fast Forward dev-tools scripts and metadata.',
4141
help: 'This command adds or updates composer.json scripts and GrumPHP extra configuration required by dev-tools.'
4242
)]

tests/Console/Command/UpdateComposerJsonCommandTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ protected function setUp(): void
6666
#[Test]
6767
public function commandWillSetExpectedNameDescriptionAndHelp(): void
6868
{
69-
self::assertSame('composer-json:update', $this->command->getName());
69+
self::assertSame('update-composer-json', $this->command->getName());
7070
self::assertSame(
7171
'Updates composer.json with Fast Forward dev-tools scripts and metadata.',
7272
$this->command->getDescription()

0 commit comments

Comments
 (0)