dandlift
The spec is the source of thruth, and is written manually in yaml (that's not that painful). The implementation comes later. Unit tests check that it conforms with the spec. [1] We also have a fake API almost completely autogenerated from the spec that's quite useful for preliminary testing of the clients.
Client code generation wasn't up to my expectations, but I've experimented with applying an handwritten template to a parsed spec and that seems viable.
Swagger as a format might have its quirks, but the tooling is there and having it as the authoritive source of thruth paid off for Us.
[1] https://bitbucket.org/atlassian/swagger-request-validator
A report is something that belongs to business, but the fact that it could be sent via email is totally accidental and depending on the technology we use (as it is the persistence layer, or the protocol which exposes the app).
Domain concerns live on domain object (which knows only other domain objects), while application concerns live in services. And here is where you have interfaces, concrete implementations and, where necessary, factories to switch or add the implementation at the flip of a switch. Eg: a ReportMailSender which implements a ReportSender, that someday get replaced with a SlackSender implementing the same interface. You want both? Wrap them on a AggregatedSender.
Now your DI framework is getting really useful.
Say we have a function with signature
f :: Int -> Int -> Int -> Int
Let's say this just add those Ints together.Now let's create another function by partially applying the initial function: f1 = f 42
f1 signature will be
f1 :: Int -> Int -> Int
Kind of "consuming" the signature. Repeat this until using up all the parameters. You end up with a function with no parameters, which map to a single Int.You could say that f3 -> Int (note, not a valid notation for the sake of example). No need for a different symbol.