J’ai toujours été frileux concernant les chaînes de caractères utilisées comme clés ou identifiants… Peut-être de vieux traumatismes liés à d’anciennes expériences en C ou C++, qui sait…
Ceci étant, une des raisons pour laquelle j’apprécie vraiment le Swift c’est bien pour son typage fort et sa grande versatilité dans l’usage des types énumérés. Ceci étant dit, on ne peut pas toujours passer par là, et c’est donc ici que se pose ma réflexion :
En plein développement d’un petit projet Vapor avec Fluent, j’ai suivi l’usage utilisé dans le projet de démo. Mais de trouver à 3 endroits différents du projet le nom du schéma en chaîne de caractères "todos"
m’a fait un peu bondir… Pareil, avec les noms des champs, que l’on retrouve dans le modèle et dans la migration mais aussi au fil des routes dans les différentes requêtes…
Alors je comprends bien que c’est un projet d’exemple pas du code de production, mais étant adepte du concept DRY (Don’t Repeat Yourself) ça me gratouille la cornée à chaque fois que je vois ça !
Du coup, j’ai opté pour une solution simple et un peu moins error-prone à mes yeux, je me permets de vous la proposer ici. J’utilise simplement une structure avec des constantes statiques qui vont me servir tout le long du projet :
struct RecordSchema {
static let schemaName = "records"
// MARK:- Fields
static let date : FieldKey = "date"
static let count : FieldKey = "count"
}
Ainsi, voici à quoi ressemble ma migration :
struct CreateCountRecord: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
database.schema(RecordSchema.schemaName)
.id()
.field(RecordSchema.date, .datetime, .required)
.field(RecordSchema.count, .uint, .required)
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
database.schema(RecordSchema.schemaName).delete()
}
}
Et mon modèle :
final class CountRecord: Model, Content {
static let schema = RecordSchema.schemaName
@ID(key: .id)
var id: UUID?
@Field(key: RecordSchema.date)
var date: Date
@Field(key: RecordSchema.count)
var count: UInt
...
}
Ça permet aussi de faire les choses bien, par exemple dans les requêtes :
.filter(RecordSchema.date, .greaterThanOrEqual, interval.start)
.filter(RecordSchema.date, .lessThanOrEqual, interval.end)
Voilà, c’était juste une réflexion en passant, qu’en pensez-vous ? C’est overkill et il n’y en a pas besoin : stringz rulez ? C’était évident, tout le monde fait comme ça, pas besoin d’en faire une tartine ? Et vous vous faites comment ?