# Composing Subjects

So far, subjects have been composed by hand.

To define their structure once, call the `NewSubjectScheme` function with a pattern, and use placeholders in braces for the variable parts:

```go
var bookSubject = architecturekit.NewSubjectScheme("/books/{book}")
```

Each segment of a subject may only contain the characters that EventSourcingDB allows: the letters `A-Z` and `a-z`, the digits `0-9`, underscores, and hyphens (see **[Subjects](/docs/eventsourcingdb/subjects)**). This applies to the literal segments of the pattern as well as to the values that fill its placeholders. The names of the placeholders follow the same rule, as `book` and `license-agreement` do, so that a typo, such as a brace too many in `{book}}`, is not taken for a name.

The function returns a `*SubjectScheme`. To compose a subject, call the `Build` function with one value per placeholder, in the order in which they appear in the pattern. Use it in every command that acts on a book:

```go
func (c AcquireBook) Subject() string {
  return bookSubject.Build(c.BookID)
}

func (c BorrowBook) Subject() string {
  return bookSubject.Build(c.BookID)
}

func (c ReturnBook) Subject() string {
  return bookSubject.Build(c.BookID)
}
```

To take a subject apart, call the `Match` function. It returns the values by placeholder name, and `false` if the subject does not follow the pattern or has a value that `Build` would refuse:

```go
values, ok := bookSubject.Match("/books/42")
// values["book"] == "42"
```

To take a single value out of a subject, call the `Value` function with the subject and the name of the placeholder. Like `Match`, it returns `false` if the subject does not follow the pattern:

```go
bookID, ok := bookSubject.Value("/books/42", "book")
// bookID == "42"
```

*Note that `Value` panics for a placeholder that the pattern does not have, such as one with a typo, whatever the subject is. The map that `Match` returns yields an empty string for such a name instead, so use `Value` for a single value, and `Match` for several values of the same subject.*

To get the pattern and the names of the placeholders, call the `Pattern` and the `Placeholders` function respectively.

To read or observe the events of all books, for example in a projection, start from the subject that all of them lie under. Call the `Root` function to get it from the scheme, rather than writing it down a second time. It returns the literal segments before the first placeholder, here `/books`, or `/` if the pattern starts with a placeholder:

```go
run := architecturekit.StartProjection(ctx, store, architecturekit.SubjectTree(bookSubject.Root()), projection)
```

*Note that other subjects may lie under the same root, such as `/books/42/reviews/7` under `/books`. Use `Match` in the projection to tell them apart.*

*Note that a malformed pattern panics, including one with a literal segment or a placeholder name that contains a character EventSourcingDB does not allow, as does calling `Build` with the wrong number of values, with an empty value, or with a value that contains such a character, for example a slash, a dot, or a space.*

Values that come from outside, such as an ID in a request, may well be empty or contain such characters, and that is not a programming error. So always check them before building a subject: call the `Check` function with the same values as `Build`. It returns an error that says what is wrong, such as which characters a value may contain, instead of panicking. The error may reach the caller of an API, for example through the function that returns a command (see **[Handling Commands over HTTP](/docs/architecturekit/v2.0/handling-commands-over-http)**), so it names the placeholder of the value, but neither the package nor the pattern, as in `value for "book" must not be empty`:

```go
if err := bookSubject.Check(bookID); err != nil {
  // ...
}
```
