I'm building a application in swift and I'm trying to follow clean architecture. In my domain layer, I have a protocol called Source, which represents any source of a particular entity (could be from network, from a local file, etc...):
protocol Source { // not the actual code, just a simple example
func getData(id: String) -> Entity
}
The getData function returns an entity defined elsewhere in the domain layer. Therefore, Source acts somewhat like a repository for Entity, if I understand the repository pattern correctly.
However, Source will also act somewhat like an entity. There will be multiple implementations of Source (I think defined in the data layer), and the user can "install" and "uninstall" particular source, meaning the application has to store the list of sources that the user has installed.
For example...
struct LocalSource {
let fileName: String
func getData(id: String) -> Entity { /* whatever */ }
}
struct NetworkSource {
let url: URL
func getData(id: String) -> Entity { /* whatever */ }
}
The existential type any Source would be used throughout the app to represent sources.
So my question is, how would I go about persisting sources? Presumably, there would be some kind of SourceRepository protocol in the domain layer that persists any Source values. But I can't figure out how this would be implemented.
Ideally, whatever code is responsible for storing Sources would not have to know any actual implementations of Source. It's very important that it's easy to add new Source implementations, ideally without having to change the SourceRepository implementation. This means that it has to persist type information so that it can reconstruct the correct concrete Source implementation when data is retrieved from the repository.
I found this great guide on encoding from/decoding to any Codable, preserving type information. However, this obviously requires Codable conformance in order to work. This is where my problem is: I could use this approach if the Source protocol inherited from Codable.
protocol Source: Codable { /* ... */ }
Therefore, any Source values could be encoded and decoded and stored in a database without losing any information.
However, this to me seems like it would mean there is some persistence-specific logic in the domain layer, which I know should be avoided.
Is there a better way to achieve this, or am I being too picky?