> For the complete documentation index, see [llms.txt](https://devon-miller.gitbook.io/test_private_book/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://devon-miller.gitbook.io/test_private_book/sstream_model/composability.md).

# Composability

Composability is improved by using stream fragments and wiring together the stream before turning the fragment into a stream and running it. Your application should be created using fragments connected with pipes. You use operations like `map` and `filter` to wrap a base stream fragment with your domain specific logic then connect the resulting fragments together to perform a sequence of operations. Either wrapping a base Stream object using `map` or connecting fragments together using `pipe` should be seen as applying domain specific knowledge. In fact, many methods on Streams are implemented using pipes.

Each fragment can be parameterized and returned in a function that you author. This allows the fragment to be customized and made more reusable. For example, if the fragment is to apply a string transformation to a specific field, the parameter may be the suffix to append:

```scala
def addSuffix(fragment: Process1[String, String], suffix: String) = fragment.map(_ + suffix)
```

These types of fragments are useful but may not as expressive as you would like. You could write the above differently:

```scala
def addSuffix(suffix: String) = pipe.lift(base:String => base + suffix)
```

This approach should be preferred because it allows a more visually decoupled syntax using the `pipe` operations e.g. `Stream.emits(Seq("blah", "hah")).through(addSuffix("-nah") ...` versus `addSuffix(Stream.emits(...)) ...`.
