Fluent Loose-Coupling with Model

In Vapor v3, Fluent was more loosely-coupled with a project’s model: One could extend an existing model to have it conform to Fluent’s mechanisms. This was great since it allowed complex models to be ignorant on Fluent, and those models could then be isolated into their own modules and linked into other projects that would use the same model but not Vapor.

Unless I’m mistaken — and I hope I am — Vapor v4 has gone all-in with Property Wrappers but has lost loose-coupling in doing so. Models now need to be explicitly changed/coded to be aware of Fluent’s PropertyWrappers.

Have I overlooked or missed a way to use Vapor v4's Fluent and still have a model completely ignorant — allowing it to be a module included in more projects — without resorting to #if and declaring stub types when Fluent isn't present?

I hope my wording isn’t too negative or aggressive… that’s not the goal. Apologies if this post doesn’t belong here.

@Q-Bert you're correct - the inclusion of property wrappers means that's the model needs to be explicitly aware of Fluent. There's no real way around this and the benefits of moving to property wrappers (such as decoupling column names, partial loading of models, more powerful relationships etc etc) fair outweighed the downsides.

From my experience when working on large apps you tend to have a number of different model representations anyway. So for instance you'd have your main DB User model that contained all of the fields in the DB. You'd then have a User.Profile that contained all the fields for a user accessing their own profile, a User.PublicProfile for other user's accessing someone's profile, a User.FriendProfile for other user's accessing someone's profile who they're friends with etc etc. Only the User type would have a password field, some contain the email, others only a username and bio etc (I've lifted that straight from a client project).

Yes there are plenty of use cases where things map one-to-one but I've also found that coupling a shared model (between a client and the database app) complicates things as well as soon as you want to version it etc.

Hope that helps. I can highly recommend writing a shared package for models that you map your types to, but I think it's good to have that separate from the DB.

1 Like