hmlongco / Factory

A new approach to Container-Based Dependency Injection for Swift and SwiftUI.
MIT License
1.83k stars 115 forks source link

How can I deal with errors thrown during resolving? #81

Closed drekka closed 1 year ago

drekka commented 1 year ago

I'm guessing this has come up before :-) But what sort of approaches are there for dealing with errors that are thrown during resolving?

For example, if I have this (which won't compile at the moment):

public extension Container {
    var service: Factory<MyProtocol> { self { try MyService() }.singleton }

And I want to somehow capture the error from the service init so I can display a message to say something went wrong, is there a way to neatly handle it?

one thought is to make the service optional and use a try?. But in my case the registration is for a singleton and the error is possible but highly unlikely so I'd kinda like to keep the registration non-optional and somehow redirect the error.

any thoughts?

hmlongco commented 1 year ago

You do have a knack, don't you? In all the years I've done this I've not had a single request for some way to handle a throwing initializer.

Regardless, if it throws then you're not going to have much of choice. That factory closure has to return something. You have two options. The first, as mentioned, is making it optional and nil.

The second depends on the type of object being returned. You could, perhaps, do...

public extension Container {
    var service: Factory<MyProtocol> { 
        self {
            do (
                return try MyService()
            } catch {
               // log error
               return StubMyProtocol()
            }
         }
        .singleton 
     }
}

If the library could fail, but is some sort of logging or analytics library, then return a mock for the rest of the world to interact with. If it's an API, then just have the mock error out when accessed.

drekka commented 1 year ago

Yeah. It's a tricky one. I have a service which is loading a bunch of data from JSON files on startup, so the problem I was addressing was what happens if something in that data is off. I've since worked around it, but it's an interesting question.