0
\$\begingroup\$

I have a question about something maybe not so much important, but every time when I have to decide, I feel it can write in another way.

Imagine I am developing and system about authentication and then I have to receive a pin after sending my phone number.

So I am writing some UseCase and, in this case, I have an interactor and a Worker as protocol.

Let's show the code

import Foundation

protocol SendPinWorker {
    func run(onResult: ((Result<Bool, Error>)->Void)?)
}

protocol SendPinUseCaseInteractor {
    func error(e: SendPINUseCaseError)
    func sent()
    func processing()
}

enum SendPINUseCaseError {
    case invalidPhone
    case couldNotSend
}

class SendPINUseCase {

    private let worker: SendPinWorker
    private let output: SendPinUseCaseInteractor
    init(worker: SendPinWorker, output: SendPinUseCaseInteractor) {
        self.worker = worker
        self.output = output
    }

    func execute(phone: String) {
        guard !phone.isEmpty else {
            self.output.error(e: .invalidPhone)
            return
        }

        self.output.processing()

        self.worker.run { [weak self] result in

            guard let self = self else {
                return
            }

            guard let sent = try? result.get(), sent else {
                self.output.error(e: .couldNotSend)
                return
            }

            self.output.sent()
        }
    }
}

Should I put these protocols and enums in another file or should I still with these structures in the same file?

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I don't think there is one true answer to your question. I personally would put them in a separate file but leaving them where they are used would also be fine. I think this question can only have opinionated answers. Also, you can declare your class as final if no other class is subclassing from it. \$\endgroup\$ – emrepun Feb 21 at 11:40
  • 1
    \$\begingroup\$ Same thoughts with @emrepun. I think this is more likely personal taste. One point to be considered is that while a wide range of various types remain in the same file, we might have a hard readable code-base to be faced with. In this situation, we would put in separate file. \$\endgroup\$ – alitosuner Feb 21 at 17:34
1
\$\begingroup\$

Consider nesting your types:

If you have two types that start with the same prefix, it's possible that one type is better nested inside the other. For example: SendPINUseCase raises SendPINUseCaseError's

class SendPINUseCase {
    enum Error {
        case invalidPhone
        case couldNotSend
    }
}

Now you have a type called SendPINUseCase.Error, it's scoped to the SendPINUseCase. If you want to use throwing functions instead of returning Result<..., Error>'s, then you would make your SendPINUseCase.Error enum conform to Swift.Error

Protocols can't be nested, but in this case you could avoid them entirely by changing your design so that, for example, execute function takes, as arguments, the callback functions involved. If you eliminate the protocols, then there's no worry about which file to put them in, and protocols are not without their problems, I would say protocols are not the right abstraction in this case.

Your SendPINUseCase is a class but doesn't encapsulate any state, so consider making it a struct.

You have execute function take a String as input, and then validate that string is a 'phone'. Instead, consider making a struct Phone that has a failable initializer, so that only valid 'Phone's can be constructed. Then execute function would take a Phone struct that you know is valid, that eliminates the invalidPhone error case entirely.

\$\endgroup\$
2
  • \$\begingroup\$ I really like your points to improve my code, I just have a point which I want to discuss with you, about the Protocols. I chose to use them because I thought it was a good way to mock and create spies for unit tests, For example, I can make spies for Interactor and mock to Worker, I wonder to know what do you think about that? \$\endgroup\$ – ViTUu Feb 22 at 21:58
  • \$\begingroup\$ Too hard to explain in a reply here - search for "How to Control the World" by Stephen Celis at NSSpain \$\endgroup\$ – Shadowrun Feb 24 at 9:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.