Why does Apple recommend using the highest level of abstraction when implementing concurrency and what does it mean?

In a Ray Wenderlich tutorial, the intructor said that Apple recommends using the "highest layer of abstraction" when using concurrency, therefore choosing Operations over Grand Central Dispatch.


What does this mean and what is the reason for this?

Accepted Reply

As I’m sure you’re aware, there’s often a trade off between abstraction and flexibility. To consider an example outside of the area of concurrency,

UIBezierPath
is a lot easier to use then the low-level Core Graphics API, but the latter can do a lot more.
Operation
versus Dispatch is a classic example of this:
  • Operation
    defines a high-level structure and offers some great features within that structure.
  • Dispatch is super flexible, but if you want advanced features you have to build them yourself on top of its primitives.

However, there’s another important point here, one related to encapsulation and code reuse.

Operation
encourages you to separate concurrent work out of your main codebase and in to small, reusable concurrent components. You can then join those components together in different ways in different parts of your program (or, for that matter, in completely different programs).

You can, of course, do exactly this sort of thing with Dispatch, but you have to start by defining your own structure. If your program does something unique, something that’s way outside of the structure defined by

Operation
, then it would make sense to do this extra work. If not, it makes sense to use the existing structure defined by
Operation
.

Or, as I like to say:

Operation
is to Dispatch as
NSObject
is to
malloc
(-:

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

As I’m sure you’re aware, there’s often a trade off between abstraction and flexibility. To consider an example outside of the area of concurrency,

UIBezierPath
is a lot easier to use then the low-level Core Graphics API, but the latter can do a lot more.
Operation
versus Dispatch is a classic example of this:
  • Operation
    defines a high-level structure and offers some great features within that structure.
  • Dispatch is super flexible, but if you want advanced features you have to build them yourself on top of its primitives.

However, there’s another important point here, one related to encapsulation and code reuse.

Operation
encourages you to separate concurrent work out of your main codebase and in to small, reusable concurrent components. You can then join those components together in different ways in different parts of your program (or, for that matter, in completely different programs).

You can, of course, do exactly this sort of thing with Dispatch, but you have to start by defining your own structure. If your program does something unique, something that’s way outside of the structure defined by

Operation
, then it would make sense to do this extra work. If not, it makes sense to use the existing structure defined by
Operation
.

Or, as I like to say:

Operation
is to Dispatch as
NSObject
is to
malloc
(-:

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Ok. That makes sense.


However, it seems to me that Grand Central Dispatch would be a higher level of abstraction than Operation, not Operation the higher level of abstraction as that video said. Wouldn't you agree?

After a while, it comes down to what you regard as "abstraction". The difference between Operation and Dispatch is that Operation contains more built-in functionality. For example, Operations have the concept of dependencies, so you can easily make one Operation wait for any combination of others to complete. Similarly, Operation has a more sophisticated concept of cancellation than Dispatch.


That's one form of abstraction — Operation is usable as-is for a wider range of cases.


By contrast, Dispatch is a more generalized mechanism. It can be incorporated into even more elaborate use cases, at the cost of supplying the "tooling" that adapts it to each case.


That's another form of abstraction — Dispatch is less restrictive on what you can do.


In truth, though, Operation and Dispatch are different mainly in their history. Operation is somewhat older than GCD, and it would actually be more convenient if they were both the same thing. For example, it's annoying that you can configure notifications to be delivered on an OperationQueue, but not a DispatchQueue, whereas other things are delivered on a DispatchQueue and not an OperationQueue. But it took a good while for the two capabilities to evolve to their current near-neighbor behavior.

Not sure it's a matter of choosing one over the other.


See h ttps://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch

For example, it's annoying that you can configure notifications to be delivered on an OperationQueue, but not a DispatchQueue, whereas other things are delivered on a DispatchQueue and not an OperationQueue.

Indeed. One saving grace here is the

underlyingQueue
property of
OperationQueue
, which lets set up a single serial queue that’s useful for both
Operation
and Dispatch.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

That's something for me to take note of and remember -- underlyingQueue. Thanks for that pointer.