Improvements

This commit is contained in:
Keyvan Akbary
2022-06-18 12:52:55 +02:00
parent 1c815834fc
commit 788f26b15e
18 changed files with 49 additions and 50 deletions

View File

@@ -30,9 +30,9 @@ framework:
# Query Transports
# It makes no sense to queries to
# have an async transport. It has
# to be sync so the customer can
# get back the response
# have an asynchronous transport. It has
# to be synchronous so the customer can
# get back the response.
queries_sync: 'sync://'
# Dead letter box
@@ -49,7 +49,7 @@ framework:
# Events can be run synchronously, however
# all the benefits like performance and
# transaction isolation comes when using
# transaction isolation come when using
# the asynchronous transport.
Cheeper\Chapter4\DomainModel\DomainEvent: events_async

View File

@@ -36,9 +36,9 @@ framework:
# Query Transports
# It makes no sense to queries to
# have an async transport. It has
# to be sync so the customer can
# get back the response
# have an asynchronous transport. It has
# to be synchronous so the customer can
# get back the response.
queries_sync: 'sync://'
# Projection Transports
@@ -49,7 +49,7 @@ framework:
failed_messages: '%env(MESSENGER_TRANSPORT_BASE_DSN)%/failed_messages'
routing:
# With a proper UX, almost all the commands should
# be run asynchronously.However, some commands can
# be run asynchronously. However, some commands can
# be defined to run synchronously.
Cheeper\Chapter7\Application\Author\Command\SignUpCommand: commands_sync
Cheeper\Chapter7\Application\Author\Command\FollowCommand: commands_async
@@ -57,7 +57,7 @@ framework:
# Events can be run synchronously, however
# all the benefits like performance and
# transaction isolation comes when using
# transaction isolation come when using
# the asynchronous transport.
Cheeper\Chapter7\DomainModel\DomainEvent: events_async

View File

@@ -12,7 +12,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
//snippet post-cheep-command
#[AsCommand(name: "app:post-chepp", description: "Post cheep from command line")]
#[AsCommand(name: "app:post-chepp", description: "Post Cheep from command line")]
final class PostCheepCommand extends Command
{
protected static $defaultName = 'app:post-cheep';

View File

@@ -57,13 +57,13 @@ final class ComplexPostCheepController extends AbstractController
);
try {
$logger->info('Executing SignUp command');
$logger->info('Executing signup command');
$entityManager->wrapInTransaction(function () use ($command, $postCheepHandler, $logger): void {
($postCheepHandler)($command);
$logger->info('SignUp command executed successfully');
$logger->info('Signup command executed successfully');
});
} catch (AuthorDoesNotExist | InvalidArgumentException $exception) {
$logger->error('SignUp command failed');
$logger->error('Signup command failed');
throw new BadRequestHttpException($exception->getMessage(), $exception);
}
//end-snippet

View File

@@ -31,9 +31,9 @@ final class GetFollowersCounterController extends AbstractController
);
/**
* In case of errors like the author does not exist, you can:
* In case of errors like the Author is not existing, you can:
* A) Let your framework catch the Exceptions and automatically
* generate 404 o 500
* generate 404 or 500
* B) Do it manually here in the Controller, using a try block
* and multiple catch blocks
*

View File

@@ -41,7 +41,7 @@ final class FromScratch
PostCheep::fromArray([
'author_id' => '527cab4c-30a8-4d6a-bf7a-157910d569e5',
'cheep_id' => '719ac125-83a9-4d6e-94da-493891b8f8b2',
'message' => 'New cheep!',
'message' => 'New Cheep!',
])
);
//end-snippet

View File

@@ -46,7 +46,7 @@ final class FromScratchWithCustomMiddleware
PostCheep::fromArray([
'author_id' => '527cab4c-30a8-4d6a-bf7a-157910d569e5',
'cheep_id' => '719ac125-83a9-4d6e-94da-493891b8f8b2',
'message' => 'New cheep!',
'message' => 'New Cheep!',
])
);
//end-snippet

View File

@@ -77,7 +77,7 @@ final class Author
public function compose(string $message): Cheep
{
if (!$this->id) {
throw new \RuntimeException('Author id has not been assigned yet');
throw new \RuntimeException('Author ID has not been assigned yet');
}
return Cheep::compose($this->id, $message);

View File

@@ -28,7 +28,7 @@ class Follow
* implementing an Observer pattern with
* Subscribers that will publish the triggered
* Domain Events into a queue system like
* Rabbit. It's useful for Legacy projects
* Rabbit. It's useful for legacy projects
* because you can trigger any Domain Event
* from any place in your code, not only
* Entities.

View File

@@ -31,7 +31,7 @@ final class CountFollowersQueryHandler
$followersCount = count($this->followRepository->toAuthorId($authorId));
// Other option would be with a counter method in the Repository
// Another option would be with a counter method in the Repository
// $followersCount = $this->followers->countOfAuthorId($authorId));
return new CountFollowersResponse(

View File

@@ -28,10 +28,10 @@ final class CheepPostedEventHandler
);
foreach ($follows as $follow) {
// Sending the projection to be processed
// asynchronously helps on improving
// Sending the Projection to be processed
// asynchronously helps improve
// performance by distributing the tasks
// between multiple workers
// between multiple workers.
$this->projectionBus->project(
new AddCheepToTimelineProjection(
authorId: $follow->fromAuthorId()->toString(),
@@ -43,10 +43,10 @@ final class CheepPostedEventHandler
)
);
// This is an example on how to straightly do
// This is a straightforward example of how to do
// it with a Redis class instance. This approach
// is synchronous. Depending on the case, it could
// be the right choice.
// be the correct choice.
//
// $this->redis->lPush(
// sprintf("timelines_%s", $follow->fromAuthorId()->toString()),

View File

@@ -27,12 +27,11 @@ final class AuthorFollowedEventHandler
)
);
// Other actions, like notifying the author
// about the new follower can be added here.
// Other actions, like notifying the Author
// about the new Follower can be added here.
// Alternatively, a more scalable design is
// to create one Event Handler for each of
// the needed actions to happen in reaction.
// All of those listening to the same
// to create an Event Handler for each of
// action that has to happen per
// AuthorFollowed Domain Event.
// @see: WhenAuthorFollowedThenIncrementFollowersProjectionEventHandler
// @see: WhenAuthorFollowedThenWelcomeAuthorEventHandler

View File

@@ -36,12 +36,12 @@ final class Author
// or an alternative way of instantiating
// an empty instance of this object
// so we can change the internal fields
// when replaying events
// when replaying Events.
}
// The public interface of an Event Sourced
// Entity should still be the same as shown
// in the other chapters
// in the other chapters.
public static function signUp(
AuthorId $authorId,
UserName $userName,
@@ -53,7 +53,7 @@ final class Author
?BirthDate $birthDate = null
): self {
// Regular semantic constructors
// still apply as a proper design
// still apply as a proper design.
$obj = new self();
$obj->authorId = $authorId->toString();
@@ -79,7 +79,7 @@ final class Author
// The public interface of an Event Sourced
// Entity should still be the same as shown
// in the other chapters
// in the other chapters.
public function changeEmail(EmailAddress $newEmail)
{
// If an Entity method invokes an

View File

@@ -32,11 +32,11 @@ final class EventSourcedAuthorRepository implements AuthorRepository
/*
public function ofUserName(UserName $userName): ?Author
{
// When doing Event Sourcing, Repositories
// responsibility is reduced to hold
// a finder by id, and add.
// In Event Sourcing, a Repository's
// responsibility is limited to providing
// a finder by ID and an add method.
// Other finder methods become
// a Projection
// a Projection.
}
*/

View File

@@ -17,11 +17,11 @@ final class CountFollowersQueryHandlerTest extends TestCase
{
/**
* @test
* @Given Non Existing Author
* @Given Non-Existent Author
* @When Counting Followers
* @Then Non Existing Author Exception Should Be Thrown
* @Then Non-Existent Author Exception Should Be Thrown
*/
public function nonExistingAuthor(): void
public function nonExistentAuthor(): void
{
$this->expectException(AuthorDoesNotExist::class);
$this->expectExceptionMessage('Author "3409a21d-83b3-471e-a4f1-cf6748af65d2" does not exist');

View File

@@ -16,11 +16,11 @@ final class CountFollowersQueryHandlerTest extends TestCase
{
/**
* @test
* @Given Non Existing Author
* @Given Non-Existent Author
* @When Counting Followers
* @Then Non Existing Author Exception Should Be Thrown
* @Then Non-Existent Author Exception Should Be Thrown
*/
public function nonExistingAuthor(): void
public function nonExistentAuthor(): void
{
$this->expectException(AuthorDoesNotExist::class);
$this->expectExceptionMessage('Author "3409a21d-83b3-471e-a4f1-cf6748af65d2" does not exist');

View File

@@ -20,11 +20,11 @@ final class CountFollowersQueryHandlerTest extends TestCase
{
/**
* @test
* @Given Non Existing Author
* @Given Non-Existent Author
* @When Counting Followers
* @Then Non Existing Author Exception Should Be Thrown
* @Then Non-Existent Author Exception Should Be Thrown
*/
public function nonExistingAuthor(): void
public function nonExistentAuthor(): void
{
$this->expectException(AuthorDoesNotExist::class);
$this->expectExceptionMessage('Author "3409a21d-83b3-471e-a4f1-cf6748af65d2" does not exist');

View File

@@ -15,11 +15,11 @@ final class CountFollowersProjectionHandlerTest extends TestCase
{
/**
* @test
* @Given Non Existing Author
* @Given Non-Existent Author
* @When Counting Followers
* @Then Non Existing Author Exception Should Be Thrown
* @Then Non-Existent Author Exception Should Be Thrown
*/
public function nonExistingAuthor(): void
public function nonExistentAuthor(): void
{
$authorId = '1c22ed61-c305-44dd-a558-f261f434f583';