2

I am pretty new to async programming and the whole stream stuff, since i have a web programming background with php, where async programming and streams isn't really a big topic most time.

I try to implement clean archtiecture in my next application where i use the concept of use cases to invoke business logic and receive its result.

Now i am at a point, where some of the use cases (and its business logic behind) is taking a bit of time to finish. But i wanna have "status updates" in between and show them to the user ... for example "determine current gps location" is such a use case and will run for a while. The current location should be shown to the frontend immediately whenever its changed in the running use case.

My idea was to return a stream from the use case and let some logic listen on the frontend side (in my case the BLOC logic).

I don't know if this has necessarily to do with clean architecture, but is it a good idea to return a stream from a use case instead of a completed result of a method invocation? Since the latter is what i am used to in my previous programming background.

Would this introduce some kind of dependency or at least a design flaw somehow? Architecturewise the communication direction should be still towards the core application, since the use case just still dont know anything from the outside, but the outside (frontend) does know something from the use case (stream) ...

Any thoughts on this or other common solutions?

3 Answers 3

5

As a C# guy, at a first glance, I tended to agreed to @GregBurghardt's answer. Then I had a look into the documentation of streams in Dart, which says:

A stream is a sequence of asynchronous events. It is like an asynchronous Iterable—where, instead of getting the next event when you ask for it, the stream tells you that there is an event when it is ready.

So streams in Dart are a - apparently standard - way of implementing asynchronous events, like an asynchrounous event stream of status messages. It is probably as idiomatic in Dart as an (synchronous) IEnumerable in C#, and not restricted to network or file I/O.

So in short: go ahead, I think your approach is fine.

3

I associate streams with infrastructure-related code. As such, I would not expect a use case to return a stream.

That being said, if the stream object is an interface or abstract class, you achieve decoupling. This still allows for polymorphism and mocking during unit tests. One of the goals of clean architecture is to make code easier to test. You could argue that an interface for a stream gives you testable code.

While I think you could get things to work using streams, I do believe it would be surprising to other developers since streams are more associated with network connectivity, file systems, and other forms of I/O — infrastructure. These are typically resources that require careful handling and cleanup to avoid memory leaks or locking a resource so that other processes cannot use it. To me, this communicates a different intent than what I think you are aiming for.

Events are the more idiomatic solution here, because they are a general solution in situations where a problem requires decoupling and/or asynchronous behavior. Some languages, like C#, have native support for events as a base-level feature of the language. For other languages, a simple list of callback functions or objects supporting a standardized interface can suffice. More generally, research event-driven programming for more information.

The nice thing about events is that the pattern does not assume which layer of the architecture you are in. Events are a good solution in many cases where some logic finishes processing at a later and unpredictable time, or in cases where you legitimately need to support concurrent programming. A related buzzword to consider when dealing with asynchronous business logic, especially when dealing with micro services, is eventual consistency.

That doesn't mean a stream isn't useful, or won't be part of the solution. If some other service running in a different process needs updates, streams could be a good solution, but more often these would take the form of some sort of network socket connection and message passing — think: message queues. At the point where your application communicates across processes or across the network, you are solidly in the "infrastructure" layer of clean architecture. Events raised by the domain or use case layers would likely have some infrastructure code as listeners, which might then update a stream object or send an HTTP message to another component.

So, the answer could be both: events in the use case and domain layers, where infrastructure code could be listening for those events. Upon responding to an event, the infrastructure code would likely use some sort of stream or socket to forward a message on to another process or service across the network. In your case, it could send a message back to the end user using a Web Socket.

A simpler alternative would be for the use case to return some sort of identifier that gets passed back to the user interface, and the client can poll the backend for status updates.

3
  • Thank you very much for this extensive answer, it gives me a lot input to think about. Using some IDs as suggested in the last part of your answer implies, that the use case has to carry a state about the requested position. Also something i never came in touch in PHP, since there is only one linear call which is gone when the scripts ends ... on the other hand, requesting users data from DB also is some kind of state, the use case requests from somewhere ... all in all it seems, that it going to be very complicated
    – Jim Panse
    Commented Nov 21, 2023 at 8:27
  • 1
    @JimPanse: to be honest, Doc Brown's answer is probably more idiomatic for Dart. I missed that tag in your question, so my answer is generalized for many programming languages. Commented Nov 21, 2023 at 12:33
  • While i also tend to Doc Browns view, i like your answer in general. Thank you for your effort!
    – Jim Panse
    Commented Nov 21, 2023 at 16:22
0

I think so you can use the concept of websockets here to communicate or transfer data between backend and frontend.

Some api would be constantly update the database and the updated document will be returned to frontend using websockets.

Maybe can refer PubSub type of arch for this. [Just a wage idea!]

Happy to discuss more if required Thanks

1
  • 1
    Thanks for your input. Isn't the idea of websockets very similar to streams? I would really like to avoid async code as much as possible, since it seems it gives a lot of headache^^
    – Jim Panse
    Commented Nov 21, 2023 at 8:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.