Skip to content

Commit

Permalink
GitBook: [master] 2 pages modified
Browse files Browse the repository at this point in the history
  • Loading branch information
tokmac authored and gitbook-bot committed Oct 5, 2020
1 parent a10db09 commit f53087a
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 15 deletions.
4 changes: 2 additions & 2 deletions docs/cronus-framework/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Overview

By default, Cronus and its sub-components have good default settings. However not everything can be auto-configured, such as connection strings to databases or endpoints to various services.
By default, Cronus and its sub-components have good default settings. However, not everything can be auto-configured, such as connection strings to databases or endpoints to various services.

## Cronus

Expand All @@ -14,7 +14,7 @@ Cronus uses this setting to personalize your application. This setting is used f
* Cassandra EventStore names
* Cassandra Projection store names

Allowed Characters: `Cronus:BoundedContext` must be alphanumeric character or underscore only: `^\b([\w\d_]+$)`'
Allowed Characters: `Cronus:BoundedContext` must be an alphanumeric character or underscore only: `^\b([\w\d_]+$)`'

#### `Cronus:Tenants` >> _string\[\] \| Required: yes_

Expand Down
45 changes: 32 additions & 13 deletions docs/cronus-framework/domain-modeling/aggregate.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ Aggregates represent the business models explicitly. They are designed to fully

### Aggregate root

Creating an aggregate root with Cronus is as simple as writing a class that inherits `AggregateRoot<TState>` and a class for the state of the aggregate root.
Creating an aggregate root with Cronus is as simple as writing a class that inherits`AggregateRoot<TState>` and a class for the state of the aggregate root.

```csharp
public class Concert : AggregateRoot<ConcertState>
{
Concert() {} // keep the private constructor
Concert() {} // keep the private parameterless constructor
public Concert(string name, Venue venue, DateTimeOffset startTime, TimeSpan duration)
{
// ...
// business logic for creating a concert
}

public void RegisterPerformer(Performer performer)
{
// ...
// business logic for registering a performer
}

// ...
Expand All @@ -27,9 +27,11 @@ public class Concert : AggregateRoot<ConcertState>

### Aggregate root state

Use the abstract helper class `AggregateRootState<TAggregateRoot, TAggregateRootId>`. Also, you can implement the `IAggregateRootState` by yourself in case inheritance is not a viable option.
The aggregate root state keeps current data of the aggregate root and is responsible for changing it based on events raised only by the root.

To change the state of an aggregate root, create method event handlers for each event with method signature `public void When(Event e) { ... }`.
Use the abstract helper class `AggregateRootState<TAggregateRoot, TAggregateRootId>` to create an aggregate root state. It can be accessed in the aggregate root using the `state` field provided by the base class. Also, you can implement the `IAggregateRootState` interface by yourself in case inheritance is not a viable option.

To change the state of an aggregate root, create event-handler methods for each event with a method signature `public void When(Event e) { ... }`.

```csharp
public class ConcertState : AggregateRootState<Concert, ConcertId>
Expand All @@ -41,26 +43,26 @@ public class ConcertState : AggregateRootState<Concert, ConcertId>

public override ConcertId Id { get; set; }

public string Name { get; set; }
public string Name { get; private set; }

public Venue Venue { get; set; }
public Venue Venue { get; private set; }

public DateTimeOffset StartTime { get; set; }
public DateTimeOffset StartTime { get; private set; }

public TimeSpan Duration { get; set; }
public TimeSpan Duration { get; private set; }

public List<Performer> Performers { get; set; }
public List<Performer> Performers { get; private set; }

public void When(ConcertAnnounced @event)
{
// ...
// change the state here ...
}
}
```

### Aggregate root id

All aggregate root ids must implement the `IAggregateRootId` interface. Since Cronus uses URNs for ids that will require implementing the URN specification as well. If you don't want to do that, you can use the provided helper base classes `AggregateRootId`, `AggregateUrn` or `Urn`. The example uses `AggregateRootId` because it inherits the other two and it is the easiest to implement.
All aggregate root ids must implement the `IAggregateRootId` interface. Since Cronus uses [URNs](https://en.wikipedia.org/wiki/Uniform_Resource_Name) for ids that will require implementing the [URN specification](https://tools.ietf.org/html/rfc8141) as well. If you don't want to do that, you can use the provided helper base class `AggregateRootId`.

```csharp
public class ConcertId : AggregateRootId
Expand All @@ -73,3 +75,20 @@ public class ConcertId : AggregateRootId
}
```

Another option is to use the `AggregateRootId<T>` class. This will give you more flexibility in constructing instances of the id. Also, parsing URNs will return the specified type `T` instead of `AggregateUrn`.

```csharp
public class ConcertId : AggregateRootId<ConcertId>
{
const string RootName = "concert";

ConcertId() { }
public ConcertId(string id, string tenant) : base(id, RootName, tenant) { }

protected override ConcertId Construct(string id, string tenant)
{
return new ConcertId(id, tenant);
}
}
```

0 comments on commit f53087a

Please sign in to comment.