5 ms·
I've been using service objects / operations in my apps pretty consistently for half a decade, but that's a red herring. That statement is about using AR to que
by bascule 10y ago
I've been using service objects / operations in my apps pretty consistently for half a decade, but that's a red herring. That statement is about using AR to query and manipulate data, which is orthogonal to a service layer. Service objects aren't going to fix the lack of optimistic/pessimistic locking in DataMapper.
- eropple 10y agoI don't know what you mean by "service objects", but my point is that ActiveRecord requires you to have a line to the database in order to actually populate a database. This is really shit for a SOA; you should not require a connection to the user database to be able to make heads or tails of an object from your authn/authz service. It is so completely unacceptable that I consider it completely disqualifying (to say nothing of AR's other problems; if I had to use an ORM, which I don't because DALs are fairly trivial in Ruby, I would use Sequel). This is why I use Virtus and ROM.
- neon_electro 10y agoCould you point to any resources for someone who has been learning stock Rails/ActiveRecord to learn more about the approach you prefer?
- bascule 10y agoOh, so you're talking about SOA / "microservices" and Claims-Based Identity (or rather, Claims-Based Identity is what you should be using). Well, an ORM is totally the wrong way to go about expressing user identities in a distributed system. As it were I wrote the AuthN/AuthZ library Square uses to solve this problem: https://github.com/square/rails-auth https://github.com/square/rails-auth The objects we build for representing user identities are POROs. No need for every app to have a database connection to a shared user service, or to go through an ORM. I'm somewhat confused what alternative you're even proposing here: are you doing something weird like Marshalling ORM objects between services?
- eropple 10y agoYou're right in that claims-based identity is the better approach; users was not the best example, but I wrote that post more hastily than I should have. =) But any distributed service with single-source-of-truth ownership of a domain object is going to be totally hosed by ActiveRecord; to handle it without every service having a database connection to every other service's datastore you end up with something like a conversion step from Magic Model Object to a PORO, and that sucks wind. (In my own case, I have a service architecture because I literally have to; I need to run services in multiple AWS regions. It would be nice to be able to not care and fart everything into a single monolithic application, but them's the breaks. I tend to think that almost every sufficiently complex or sufficiently scaled application ends up in this state, too.) With Virtus/rom-model (or I guess the newer dry-types, though I haven't used it), I don't, because my--versioned, because my APIs already require compatibility--model objects are aware of their own contents, and I can trivially marshal objects over the wire. (I also don't have to go look at the database schema to know what my object is. Big plus.)
- bascule 10y agoto handle it without every service having a database connection to every other service's datastore you end up with something like a conversion step from Magic Model Object to a PORO, and that sucks wind. I actually prefer the distinction: serialized domain objects do not have access to the full richness of the ORM API, so having a separate class representing the specific behavior of an API-wrapper makes a lot more sense to me. Something like ActiveModel::Serializers wraps up a lot of the boilerplate while also letting you retrieve nested object graphs in a single request: https://github.com/rails-api/active_model_serializers https://github.com/rails-api/active_model_serializers That said at Square we generally use protobuf-based RPC for our service-to-service requests, because we have a polyglot SOA so it's important for our services to produce and consume protos to support more languages than just Ruby.
- xtian 10y agoFor the vast majority of apps, SOA is detrimental to productivity and maintainability. For some cases it is the right choice but I don't think anyone is arguing that these are the cases for which AR was designed. Can't you recognize the usefulness of a hammer even if you need a screwdriver for your task?
- eropple 10y agoWhen that hammer inevitably is used on screw-related tasks, I get a bit touchy. ActiveRecord in particular is one of the bigger offenders (well, Rails full-stop is one), being applied in all sorts of ways that somebody (hi) ends up having to fix, which is why I mention it. I don't agree with regards to SOAs and either productivity or maintainability, but I also tend to work on systems that have concrete needs for scale and I also divorce it from the microservice craze (which I regard as a rather pathological case). But that's kind of off-topic.