SHARE
TWEET

Untitled

a guest Oct 21st, 2019 78 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Deps1.playground
  2.  
  3. import UIKit
  4.  
  5. // Design issues / decisions:
  6. //
  7. // - should "providing" protocols use funcs or vars?
  8. //   - i.e. `var serviceA` vs `func serviceA()`
  9. //
  10. // - for deps which themselves have deps ("internal nodes of the deps tree"),
  11. //   should they take a deps object or should we ban them from using the deps pattern?
  12. //   - i.e. if C depends on A and B, should we `class ServiceC { init(deps: Deps) }`
  13. //     or should we `class ServiceC { init(a: ServiceA, b: ServiceB) }`?
  14. //
  15. // - if internal nodes take a deps object, the deps object will run into a bootstrapping problem
  16. //   (`ServiceC.init()` needs a `Deps` and `Deps.init()` needs a `ServiceC`)
  17. //   - we can get around this by using force-unwrapped vars (and a static builder method)
  18. //   - or avoid the issue by banning internal nodes from using the deps pattern.
  19. //
  20. // - if internal nodes are banned from the deps pattern, we lose the ability to replace
  21. //   a dep at run-time and have every part of the system automatically start using the new
  22. //   dep (if ServiceC uses ServiceA (given via init), replacing Deps.serviceA
  23. //   at runtime with a fake does not affect ServiceC, which will still use the original A).
  24.  
  25.  
  26.  
  27. // This playground explores:
  28. // - "providing" protocols use vars
  29. // - "internal" nodes use deps pattern
  30. // - use force-unwrap to work-around the bootstrapping problem
  31.  
  32. // Ultimately, it looks like this approach will not work because `var foo: Foo!`
  33. // does not satisfy a `var foo: Foo { get }` protocol.
  34.  
  35.  
  36.  
  37. // service data types
  38.  
  39. public typealias A = Int
  40. public typealias B = Int
  41. public typealias C = (A,B)
  42.  
  43.  
  44.  
  45. // service protocols
  46.  
  47. public protocol AServicing {
  48.     func getAs() -> [A]
  49. }
  50.  
  51. public protocol BServicing {
  52.     func getBs() -> [B]
  53. }
  54.  
  55. public protocol CServicing {
  56.     func getCs() -> [C]
  57. }
  58.  
  59.  
  60.  
  61. // service implementations
  62.  
  63. public class AService: AServicing {
  64.     public func getAs() -> [A] {
  65.         return [1,2,3]
  66.     }
  67. }
  68.  
  69. public class BService: BServicing {
  70.     public func getBs() -> [B] {
  71.         return [11,12,13]
  72.     }
  73. }
  74.  
  75. public class CService: CServicing {
  76.  
  77.     public init(deps: AServiceProviding & BServiceProviding) {
  78.         _deps = deps
  79.     }
  80.  
  81.     public func getCs() -> [C] {
  82.         return Array(zip(_deps.aService.getAs(), _deps.bService.getBs()))
  83.     }
  84.  
  85.     private let _deps: AServiceProviding & BServiceProviding
  86. }
  87.  
  88.  
  89.  
  90. // deps protocols
  91.  
  92. public protocol AServiceProviding {
  93.     var aService: AServicing { get }
  94. }
  95.  
  96. public protocol BServiceProviding {
  97.     var bService: BServicing { get }
  98. }
  99.  
  100. public protocol CServiceProviding {
  101.     var cService: CServicing { get }
  102. }
  103.  
  104.  
  105.  
  106. // deps implementation
  107.  
  108. public class Deps: AServiceProviding, BServiceProviding, CServiceProviding {
  109.     public var aService: AServicing
  110.     public var bService: BServicing
  111.     // this fails to compile because the force-unwrapped version apparently doesn't satisfy the protocol requirement:
  112.     public var cService: CServicing!
  113.  
  114.     public init(aService: AServicing, bService: BServicing) {
  115.         self.aService = aService
  116.         self.bService = bService
  117.     }
  118.  
  119.     public static func makeDeps(
  120.         aService: AServicing,
  121.         bService: BServicing,
  122.         cService: CServicing? = nil
  123.     ) -> Deps {
  124.  
  125.         let deps = Deps(aService: aService, bService: bService)
  126.         deps.cService = cService ?? CService(deps: deps)
  127.         return deps
  128.     }
  129. }
  130.  
  131.  
  132.  
  133. // Some objects which use the deps:
  134.  
  135. public class ControllerAB {
  136.     public let deps: AServiceProviding & BServiceProviding
  137.     public init(deps: AServiceProviding & BServiceProviding) {
  138.         self.deps = deps
  139.     }
  140.  
  141.     public func total() -> Int {
  142.         return (deps.aService.getAs() + deps.bService.getBs())
  143.             .reduce(0, { $0 + $1 })
  144.     }
  145. }
  146.  
  147. public class ControllerC {
  148.     public let deps: CServiceProviding
  149.     public init(deps: CServiceProviding) {
  150.         self.deps = deps
  151.     }
  152.  
  153.     public func total() -> Int {
  154.         return deps.cService.getCs()
  155.             .reduce(0, { $0 + $1.0 + $1.1 })
  156.     }
  157. }
  158.  
  159.  
  160.  
  161. // use real services:
  162.  
  163. let a = AService()
  164. a.getAs()  // [1,2,3]
  165.  
  166. let b = BService()
  167. b.getBs()  // [11,12,13]
  168.  
  169. let deps1 = Deps.makeDeps(aService: a, bService: b)
  170.  
  171. let c = CService(deps: deps1)
  172. c.getCs()  // [(1,11),(2,12),(3,13)]
  173. deps1.cService.getCs()  // [(1,11),(2,12),(3,13)]
  174.  
  175. let controllerab1 = ControllerAB(deps: deps1)
  176. controllerab1.total()  // 42
  177.  
  178. let controllerc1 = ControllerC(deps: deps1)
  179. controllerc1.total()  // 42
  180.  
  181.  
  182.  
  183. // fake A and B implementations:
  184.  
  185. public class FakeAService: AServicing {
  186.     public func getAs() -> [A] {
  187.         return [-1,-2,-3]
  188.     }
  189. }
  190.  
  191. public class FakeBService: BServicing {
  192.     public func getBs() -> [B] {
  193.         return [-11,-12,-13]
  194.     }
  195. }
  196.  
  197.  
  198.  
  199. // use fake A with real C:
  200.  
  201. let fa = FakeAService()
  202. fa.getAs()  // [-1,-2,-3]
  203.  
  204. let deps2 = Deps.makeDeps(aService: fa, bService: b)
  205. let c2 = CService(deps: deps2)
  206. c2.getCs()  // [(-1,11),(-2,12),(-3,13)]
  207. deps2.cService.getCs()  // [(-1,11),(-2,12),(-3,13)]
  208.  
  209. let controllerab2 = ControllerAB(deps: deps2)
  210. controllerab2.total()  // 30
  211.  
  212. let controllerc2 = ControllerC(deps: deps2)
  213. controllerc2.total()  // 30
  214.  
  215.  
  216.  
  217. // fake B with real C:
  218.  
  219. let fb = FakeBService()
  220. fb.getBs()  // [-11,-12,-13]
  221.  
  222. let deps3 = Deps.makeDeps(aService: a, bService: fb)
  223. let c3 = CService(deps: deps3)
  224. c3.getCs()  // [(1,-11),(2,-12),(3,-13)]
  225. deps3.cService.getCs()  // [(1,-11),(2,-12),(3,-13)]
  226.  
  227. let controller3 = ControllerAB(deps: deps3)
  228. controller3.total()  // -30
  229.  
  230. let controllerc3 = ControllerC(deps: deps3)
  231. controllerc3.total()  // -30
  232.  
  233.  
  234.  
  235. // fake A and fake B with real C:
  236.  
  237. let deps4 = Deps.makeDeps(aService: fa, bService: fb)
  238. let c4 = CService(deps: deps3)
  239. c4.getCs()  // [(-1,-11),(-2,-12),(-3,-13)]
  240. deps4.cService.getCs()  // [(-1,-11),(-2,-12),(-3,-13)]
  241.  
  242. let controllerab4 = ControllerAB(deps: deps4)
  243. controllerab4.total()  // -42
  244.  
  245. let controllerc4 = ControllerC(deps: deps4)
  246. controllerc4.total()  // -42
  247.  
  248.  
  249.  
  250. // or use a fake C directly:
  251.  
  252. public class FakeCService: CServicing {
  253.     public func getCs() -> [C] {
  254.         return [(0,0)]
  255.     }
  256. }
  257.  
  258. let fc = FakeCService()
  259. fc.getCs()  // [(0,0)]
  260.  
  261. let deps5 = Deps.makeDeps(aService: a, bService: b)
  262. deps5.cService.getCs()  // [(1,11),(2,12),(3,13)]
  263. deps5.cService = fc
  264. deps5.cService.getCs()  // [(0,0)]
  265.  
  266. let controllerab5 = ControllerAB(deps: deps5)
  267. controllerab5.total()  // 42
  268.  
  269. let controllerc5 = ControllerC(deps: deps5)
  270. controllerc5.total()  // 0
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top