swift - How to avoid having a pipeline of functions? -


i in process of writing code following things:

  1. sends request web service starts compressing database .zip file
  2. repeatedly invokes web service function checking whether database has been compressed , ready download
  3. downloads database using nsurlsessiondownloadtask
  4. unzips file , stores documents directory
  5. renames unzipped file desired name

besides that, entire process takes care of error handling using callbacks i.e. closures.

the far code follows:

func continuebyrepeatedlycheckingdatabasezipready() -> void {     let conditionclosure : ((x : string) -> bool) = {x in x == "ok"}     let repetitionclosure : ((x : string) -> string) = {result in string(result)}      requesttask(method: databasezipready()).apply(5, c: conditionclosure, f:repetitionclosure,         onsuccess: {success in             self.startdownloaddatabase()         }, onfailure: {error in             self.failure(error: error)     }) }   func startdownloaddatabase() -> void {     let databasesourceurl : nsurl = requestdatabaseurlfordownload().requesturl      downloadtask(url: databasesourceurl,         progresscallback: {received, total in          }, successcallback: {location in             self.unzippingdatabasefile(location)         }, failurecallback: {error in             self.failure(error: error)     }).resume() }  func unzippingdatabasefile(location : nsurl) {      unzip(sourceurl: location, destinationurl: filemanagement().documentsdirectory()).execute({             self.renamedatabasenameintocrmdb()             self.deletetemporalydatabasefileontheserver()         }, onfailure: {error in             self.failure(error: error)     }) } 

and forth...

however, want avoid (for sake of code testability , simplicity) having pipeline of functions such. first step, i've taken @ gof , tried find pattern suit problem. but, unfortunately none of them fit problem.

therefore, have piece of advice onto how break out dependencies between these functions i.e. behaviour? keep in mind i'm trying have code functional possible.

a couple of observations.

  1. you can remove code calls next step in process these methods , change these methods take completion handlers. then, code calls these methods trigger next step.

    func continuebyrepeatedlycheckingdatabasezipready(completionhandler: (bool)->()) -> void {     let conditionclosure : ((x : string) -> bool) = {x in x == "ok"}     let repetitionclosure : ((x : string) -> string) = {result in string(result)}      requesttask(method: databasezipready()).apply(5, c: conditionclosure, f:repetitionclosure,         onsuccess: {success in             completionhandler(success)         }, onfailure: {error in             self.failure(error: error)     }) }  func startdownloaddatabase(completionhandler: (nsurl)->()) -> void {     let databasesourceurl : nsurl = requestdatabaseurlfordownload().requesturl      downloadtask(url: databasesourceurl,         progresscallback: {received, total in          }, successcallback: {location in             completionhandler(location)         }, failurecallback: {error in             self.failure(error: error)     }).resume() }  func unzippingdatabasefile(location : nsurl, completionhandler: ()->()) {     unzip(sourceurl: location, destinationurl: filemanagement().documentsdirectory()).execute({             completionhandler()         }, onfailure: {error in             self.failure(error: error)     }) } 

    by pulling code determines next step, can unit test these methods without incurring dependencies , without having stubbing.

  2. in terms of how initiate next step in process, can call each in completion handler of prior one:

    func runwholeprocess() {     continuebyrepeatedlycheckingdatabasezipready() { success in         self.startdownloaddatabase() { location in             self.unzippingdatabasefile(location) {                 self.renamedatabasenameintocrmdb()                 self.deletetemporalydatabasefileontheserver()             }         }     } } 
  3. if don't nesting, there lots of ways establish dependencies between asynchronous tasks.

    • you can, example, wrap them in asynchronous nsoperation subclass objects, , can use dependencies between them.

    • or, if you're ok third party libraries, can use promises/futures library (such promisekit, brightfutures, or rxpromise) in can chain series of asynchronous tasks together. conflicted on promises/futures in swift: idea, i'm wary of these libraries due inconsistency between them, lack of wide-spread acceptance of futures/promises in general in swift, etc. mention sake of completeness.

i must confess don't relying on self.failure in these various methods, variety of reasons. i'd have completion blocks called upon success or failure, passing along relevant information, , retire self.failure. want make sure these methods not relying on properties of class, rather pass relevant information each requires other.


Comments

Popular posts from this blog

routing - AngularJS State management ->load multiple states in one page -

python - GRASS parser() error -

Swift game error message -