Hello, this project and all the related libraries in dry-python are simply awesome, so thank you so much!
As an aside: I only just stumbled across dry-python by a comment on SO on implementing DDD in Django. I've been struggling for many months trying to understand DDD and was beginning to think it would be far to difficult to turn around the architectural mess of a major project that I am working on. However, stories, mappers, dependencies and this cookbook are a god-send! These tools are going to enable me to migrate towards a layered architecture utopia.
I do have a couple of questions (sorry for the long post). I'd greatly appreciate any pointers.
I'm trying to understand where the Story (from the stories library) fits in terms of the Service Layer. Is it right to say that a story is a service/task, i.e. that the presentation layer invokes? However, in the docs, the Story is referred to as a business transaction and sometimes a business object. A lot of pages on the web seem to suggest that a business object and domain object are the same things. So, is a story a service or is it a domain-layer thing?
It says in the stories overview: "A business transaction doesn’t have any state" and it also states in DDD (the book) that "[the application layer] does not have state reflecting the business situation, but it can have state that reflects the progress of a task...".
Let's say, for a story in my app, the user uploads a file which is processed asynchronously (by a set of tasks in Celery). The user (on a separate 'review' screen) sees a simple progress bar (0-100%) and then the final result of the workflow (success or some failure reason). Where in DDD do you store/retrieve this state? It makes sense, maybe, to store the overall state of the workflow on the domain object / Django model, e.g.
Upload.is_validate, but then if you wanted to track where/how it failed, would you want that on the model too? And then for the progress state, currently my Celery tasks contain brittle logic to calculate and write the progress directly to a model.
I feel like I'm missing a fundamental part of building workflows and was looking towards workflow management systems (WFMS) for answers. I really love the simplicity of Stories but I am still confused on the best practices for this kind of state.
I'm back, sorry for the late response.
Yes. Stories library is a complete solution for writing services or business logic scripts. The business object terminology comes from https://dry-rb.org/gems/dry-transaction/ library which was an initial inspiration for the stories library back in 2018.
In cases where execution will be continued later like celely tasks or aiohttp coroutines we suggest to write two stories. One for schedule logic. One to be executed inside the tasks. I have this feature in mind to trace these two stories as a single one dry-python/stories#39 It will be implemented some day.
I would ask you to suggest all your ideas where our documentation could be improved.
Best regards, Artem.
Thank you, @proofit404 , for your response. That helped clear things up for me a lot.
I pulled a massive effort over the weekend and last night to fully implement a feature using stories, mappers, contracts/failure protocols and DI. I demoed it to my team today, and they were as blown away as I have been as many DDD ideas finally click into place!
Here is some feedback on the documentation (some of these points, e.g. on testing, may stray outside the scope of each library/docs).
Evaluatedworks? Does it expect the anotated property to have the same name as the entity property? What if these are different?
mapper.reader.sequencedecorators, are not explained explicitly nor what other options are available.
__call__. Since Dependencies and Stories are designed to work together it would be good if the Celery contrib could run the Story without requiring