/*:#localized(key: "WrappingUp")
 # Wrapping up

 Wrapping work in an `Operation` object trades a closure's convenience for reuse
 and control, a trade that only pays off when you need the object. Most of the
 confusion here is about timing: when the work actually runs, and when its result
 is ready. Keep the lifecycle points below straight and operations stay
 predictable.

 * An **`Operation`** is work wrapped as an object, so it can carry a name,
 state, inputs, and outputs, and later support cancellation and dependencies.
 * **`BlockOperation`** is the quick option; `.start()` runs it **synchronously
 on the current thread**, so it alone gives you no concurrency. Add it to a queue
 to get work off the main thread.
 * An **`OperationQueue`** runs operations on background threads. By default it
 runs several at once, so completion order is unpredictable; only
 **`maxConcurrentOperationCount = 1`** makes it serial and in-order.
 * **Subclass `Operation`** and override **`main()`** for reusable work with
 inputs and outputs stored as properties; keep it synchronous and it's finished
 when `main()` returns. Never call `main()` yourself: call `start()` or add to a
 queue, which manages the operation's state.
 * Operations are **one-shot** (start each instance only once, make a new one to
 rerun) and read an output only *after* the work finishes, never right after
 `addOperation`.
 * Choose GCD for simple fire-and-forget closures; choose Operations when you
 need the work as a manageable object.

 ---
 
 ## Up next

 The next chapter covers [operation dependencies and cancellation](Operation%20Dependencies%20and%20Cancellation.playgroundchapter/Overview): how to say
 "bind *after* printing," how to cancel work that's already queued, and how to
 write operations whose work outlives `main()`.

 [Previous](@previous)  |  page 9 of 9
 */
