WoW lolVery interesting ideas. I've tried so many times to totally decouple
the view from my application, in a "publisher-subscriber" way of thinking (I
think that this is something like this hexagonal architecture). I've thought
that I'd managed to get that by using a "layered architecture", but after
reading, digesting and playing a little bit with qi4j, it just feel so wrong
separating my domains in something "physical" like layered architectures
instead of modularizing it according their responsibility...

Very very neat thoughts Rickard, thanks for sharing this ideas

Best Regards

Rafael Nami

2009/3/11 Rickard Öberg <[email protected]>

> Hey,
>
> So, yesterday I tried reworking my StreamFlow workflow app into using
> the hexagonal architecture. So far I am extremely happy with the
> results. One of the things I have had big trouble with before is to
> implement the "TellDontAsk" principle. It seemed like no matter what I
> did I had to, in the end, ask for model information in various ways,
> thus showing all the inner details that I had been trying to encapsulate
> with my private mixins etc.
>
> With the hexagonal architecture, where UI can be "at the bottom", and
> considered "output", this problem went away. Let me give you an example.
> In the app there is a search field and a search result view. In a normal
> layered app there would be a UI component that takes the search string
> and sends it to the application layer, and then presents the results.
> The app layer would have a method like this:
> SearchResult search(String query);
>
> This is very problematic though: first of all the search field has to
> know about the search result view, so they are coupled. If I then also
> want to update some other part in the UI the search field has to know
> about this too. Also, it is highly likely that once I get the result, I
> have to query the application for other things in order to present the
> result.
>
> With hexagonal architecture this mess goes away. Since the flow is only
> "in->out" rather than "up-down-up", the application layer method becomes:
> void search(String query);
> The application layer performs the query. When it is done it then simply
> looks up all services that implement SearchObserver, iterates over them,
> and pass the result to them. This can be easily done with a SideEffect
> of the search method, and gives a good example of when to use
> SideEffects. The code is something like this in the SideEffect:
> @Service Iterable<SearchObserver> observers;
> @This Searcher searcher.
> public void search(String query)
> {
>    for(SearchObserver observer: observers)
>    {
>       observer.refresh(searcher.searchResult().get());
>    }
> }
> ---
> Since the app layer uses() the UI layer, one of the observers just
> happens to be the search result view, which presents the results. If
> there had been a status bar it could have also consumed the results and
> showed a message like "Found 14 matches". Or more like, a SearchStatus
> service would have Observed the search results, which would have
> produced the string, which is then in turn sent to StatusObservers, one
> of which happens to be the status bar.
>
> If the search takes a long time, the UI would be in trouble with the
> first method, as it would essentially freeze when calling search. With
> hexagonal architecture the search(string) method can accept the string,
> return immediately, and then spawn off an asynchronous search that only
> when completed notifies the observers. The time between search and
> result can be quite long, but the UI will still be responsive in
> between, without the UI having to do the thread trickery. When consuming
> the results the UI does, however, have to ensure that it is on the Swing
> thread.
>
> In any case, a key point is that the search field *does not have to
> know* how to present the results. All it does is take the string and
> send it to the application for querying. What happens then is up to the
> application and observers of the model that the processing changes.
> Input and output are separated in code, but still both are presented on
> the UI screen.
>
> In this way there *is only TELL*, no ask. All events come from the
> outside, goes to the inside (through app->domain), and then goes out
> again. And sometimes the initiator (UI) just happens to be the output too.
>
> This would also simplify testing, as the call to the app and
> introspection of the resulting model using a mock observer is quite easy
> to do.
>
> NEAT!
>
> /Rickard
>
>
> _______________________________________________
> qi4j-dev mailing list
> [email protected]
> http://lists.ops4j.org/mailman/listinfo/qi4j-dev
>
_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev

Reply via email to