J'essaie de trouver un type correct pour mes identifiants dans un programme Go conçu en utilisant "Clean Architecture" de Uncle Bob Martin.Type d'ID générique pour "Architecture propre" Go program
type UserID ...
type User struct {
ID UserID
Username string
...
}
type UserRepository interface {
FindByID(id UserID) (*User, error)
...
}
Je suivais "Clean Architecture", où le code de l'oncle Bob Martin est organisé comme un ensemble de couches (de l'extérieur dans: infrastructures, interfaces, UseCases et domaine) . L'un des principes est la règle de dépendance: les dépendances de code source peuvent uniquement pointer vers l'intérieur.
Mon type User
fait partie de la couche de domaine et si le type ID
ne peut pas être dépendante de la base de données choisi pour le UserRepository
; Si j'utilise MongoDB, l'ID peut être un ObjectId
(string
), alors que dans PostgreSQL, je pourrais utiliser un entier. Le type User
dans la couche de domaine ne peut pas connaître le type d'implémentation.
Grâce à l'injection de dépendances, un type réel (par exemple MongoUserRepository
) implémentera l'interface UserRepository
et fournira la méthode FindByID
. Puisque ce MongoUserRepository
sera défini dans les interfaces ou la couche d'infrastructure, il peut dépendre de la définition de UserRepository
dans la couche de domaine (plus interne).
Je considère en utilisant
type UserID interface{}
mais le compilateur ne sera pas très utile si le code dans l'une de la couche extérieure tente d'attribuer dans le type de mise en œuvre incorrecte. Je souhaite que la couche d'interfaces ou la couche d'infrastructure, où la base de données est spécifiée, détermine et requière le type spécifique UserID
, mais le code de couche de domaine ne peut pas importer ces informations car cela viole la règle de dépendance.
J'ai également considéré (et je utilise actuellement)
type UserID interface {
String() string
}
mais qui suppose une connaissance que la base de données utilisera les chaînes pour ses ID (j'utilise MongoDB avec son ObjectId
- synonyme de type pour string
).
Comment puis-je gérer ce problème de façon idiomatique tout en permettant au compilateur de fournir une sécurité de type maximale et de ne pas enfreindre la règle de dépendance?
Cela pourrait fonctionner. Je vais y réfléchir.(C'est en quelque sorte où je me dirigeais avec mon '' 'type UserID interface { String() chaîne }' ''). – Ralph
Je ne pense pas que cela fournisse la vérification du type de temps de compilation. Une méthode 'FindByID' de type' PgUserRepository' peut également accepter une chaîne 'MongoUserID'. Ou tout type qui implémente l'interface 'UesrID'. – abhink
@abhink Si vous avez une méthode spécifique au Pg, pourquoi utiliser l'interface au lieu du type struct comme type d'argument dans la méthode FindByID? – Nebril