lundi 11 avril 2022

Should an inter-layer interface "leak" data structures/enums from the higher layer?

When separating a program's design into layers, e.g. a model layer and a UI layer, one ideally builds a pad of interfaces between the two, so that communication is abstract (i.e. Dependency Inversion Principle). However, when doing that, there invariably comes the question of what data structures one should pass as function arguments across that layer boundary - for example, the UI layer may declare a form that collects some information, say

struct Login {
     string userName;
     string password;
}

but it could also be more complicated, like an enum of choices, e.g.

enum WifiProtocol {
     PROTOCOL_WEP,
     PROTOCOL_WPA2,
     PROTOCOL_OTHER
}

but the trick is that, because the way I understand it the Dependency Inversion Principle both says that not only do both layers communicate via said interface "padding", it also is "owned" by the higher-level layer in that changes in the lower-level one should not force a change in that interface. And if we imagine that the UI layer sits on top, with the model layer below, then the UI layer would provide an abstract set of interfaces giving different services that the user should be able to interact with, e.g.

interface ILoginService {
     void login(Login login);
}

or

interface ISetWifiSecurityService {
     void setWifiSecurity(WifiProtocol wifiProtocol);
}

but type Login and WifiProtocol is defined in the UI layer, so something in the model layer will now "see" that one. Now, there's typically a buffering, dedicated service layer inside the model before you get to the "domain core", and that "core" is supposed to be "free and pure and independent" of all UI, persistence concerns. Yet then what to do with, say, that enum (it's reasonable you could split up the Login into function parameters but the enum will need mapping, and those mapping rules need categorization as to where they go). If anything in that "core" gets on it, say to map those protocols to objects, would that constitute an objectionable "intrusion/leakage of UI concerns into the model"?

Does this mean we should "fatten" the application service sublayer of the model a bit to take on the extra responsibility of doing that mapping itself so the domain sublayer is free and clear of that UI layer-defined enum? We also don't want to duplicate that enum, either, as duplicated code that is at all liable to change really hurts the maintainability.

Aucun commentaire:

Enregistrer un commentaire