Say we want to make an application
containing the following:
operations
on selected objects
object
we want to access the status
of an associated operation
.show
, cancel
and pause
these operations from multiple views
.Then my question is the following:
operations
and their progress/status
belong in an Application Design Pattern?To put it into context here is a dummy application:
We have an application where you can apply different Filters
to Images
. Application consists of a Directory View
and Detail View
.
filter
can be applied asynchronously
to any image
from each view
. filter
-operation can be observed
and canceled
from both views
.filter-type
and image
, or if such a filter
has already produced a result
.Decoupling the Service Layer
or Network Controller
from the View
and Model
in a design pattern like MVC
or MVVM
is quite straight forward, as long as you don't provide more UX feedback
than a spinner
when there's an active network request
.
But when I am working on an application confirming to the criteria above, I always end up either
user
to change view
during an operation
Tagging
operations with the id
of the object currently processed and passing this to the views
, or looking in the Network Controller
directly from the views/view controllers
entities
for operations
, and suddenly I have a request operation
in my model
So obviously there are (very smelly) ways to come around this, but they all feel dirty and not inline with how the patterns are intended.
So purely from a software architecture and design pattern point of view, how would you approaching this?
I generally prefer a promise object for this design issue. The promise object can contain methods to cancel the operation, check on the status of the operation and even contain closures to be executed depending on what happens with the operation (success, failure, cancel, etc.).
That promise object can either be handed from view to view or can be served from the network layer upon multiple requests (view A kicks off operation, view B tries later to kick it off but it is already running so gets the same promise object).
That means that the service layer, or network layer in this case, needs to present which operations, requests, are ongoing for which object, right? Because you don't want to kick of a request just to get the promise object, in case a button should be hidden if the operation is already started. I guess you would keep these promise objects outside your app model since they don't live between sessions, and the network layer would store them by url, but how would you generally serve this back from the network layer without exposing to much the network layer to the ui?
Network layer has convenience methods for the UI to utilize to kick off requests that the user initiates. The network layer determines if a request has already started and returns the same promise. Even if the network layer kicked off the process internally (auto refresh, etc) it can still deliver the promise back to the UI if the UI tries to start the same process.
The promise objects only live as long as the operation is on-going. I actually have the operation be the true holder of the promise object and the network controller holds the queue of operations. Then when a request comes in, I search the queue for the existence of that operation and if it exists return the promise from the operation. If it doesn't exist, I create a new operation, put it in the queue and return its promise object.
The interface between the UI and the back end is the exposed methods on the network controller. The UI has no knowledge of operations, it just has a function that says "go refresh this or go get that" and gets a promise back. It does not need to know or care how the job is performed, it just knows that the promise is its way to check on the status of that operation.
Now, if it is a data refresh, then the promise isn't needed for data updates, the NSFetchedResultsController
will handle that. The promise in that situation handles "am I active" and "cancel me" type requests only.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With