hmlongco / Resolver

Swift Ultralight Dependency Injection / Service Locator framework
MIT License
2.14k stars 188 forks source link

Immutable Dependencies #128

Closed moorewes closed 2 years ago

moorewes commented 3 years ago

It would be useful to enforce immutability of an injected type.

That way, the property can't be set again after initialization.

Something like: @InjectedConstant, which would be just like @Injected, but wrappedValue and projectedValue would be computed properties, without setters.

Thoughts?

class MyObject {
   @Injected private var dependencyA: A
   @InjectedConstant private var dependencyB: B

   func foo() {
      dependencyA = A()  // compiles
      dependencyB = B() // does not compile
   }
}

(edit: code snippet typo)

hmlongco commented 3 years ago

Ummm... I guess I'd like to know more about when, specifically, such behavior would be useful?

Being about to alter an @Injected value can come in handy when doing mocking and unit tests, and as such I wouldn't want to change the default behavior. But I'd also be leery of making duplicates of all of the @Injected property wrappers without a better understanding of the benefits.

moorewes commented 3 years ago

Thanks for the quick reply.

Fair question - this behavior would be useful for the same reason it's useful to have vars as well as lets in Swift. Compiler enforced immutability being the main benefit, but perhaps some performance/optimization gains as well.

I can see how this could limit unit testing/mocking flexibility for certain approaches, which would be a consideration when choosing between a variable and a constant.

hmlongco commented 2 years ago

Disinclined to build this into Resolver at this point in time, especially since as mentioned it would tend to proliferate all of the various property wrappers and since it's relatively trivial you to clone the existing wrapper and implement it yourself if you truly see value in it.