3

Our db is optimized for minimum join count (partially denormalized). E.g. our User entity contains account data (nickname, facebook id, etc), user numerical statistics (total games played, total wins, etc), guild related user information (guild id, membership type, etc) and so on - everything in the same table.

We use ORM - NHibernate. The user table is mapped (with all the fields) to User class.

Now I'm refactoring a model class AccountManagementService that provides a possibility to do some actions on an enclosed User. The model has the two dependencies: NHibernate and the User entity. The model logic is strictly tied to ORM methods (performs selects, does updates).

I think it's bad that the model knows about so many fields which it's not going to use. It doesn't need User.GuildId, statistics, etc. But since the model already should use ORM it's logical that it should know about entity classes.

I'm also worried that some operations with User should be done only through special services but other services theoretically can access and change any of the User's fields. E.g. AccountManagementService should not change User.Money directly but use UserMoneyService instead. But from a compiler viewpoint such change is perfectly valid.

Should I introduce other abstraction layers between services and entities to control an access and how can I do it? Can you see any other possibilities to improve the situation?

Vlad
  • 311
  • 2
  • 11

3 Answers3

1

You would probably want some layer(Facade pattern may be) that would expose only the necessary fields. Sounds like right now you are exposing your ORM models to all the layers and creating a spaghetti/unsecure code :)

Start by defining clear responsibilities of each layer and only exposing the model data that is necessary for the layers above.

If it requires a translation layer in between, so be it.

Alexus
  • 2,368
  • 15
  • 24
1

In the bigger view, this sounds like an Anemic domain model (Martin Fowler - https://en.wikipedia.org/wiki/Anemic_domain_model)

These Data Access Objects are a direct mapping to the database and do not reflect your business logic.

The way to go would probably be a CQRS (https://en.wikipedia.org/wiki/Command–query_separation) model, but it would probably force you to redo the full system.

You should probably read: Patterns of enterprise application architecture. I think you will find it a good resource. Its main topic is database mapping patterns.

There is really no escape from a middle layer here. I would do a class to represent each business domain and then map it to the DAOs. There will be no escape from spagetti

eviloop
  • 159
  • 5
  • Forgot to say. The pattern is called Remote Facade: http://martinfowler.com/eaaCatalog/remoteFacade.html. I would also use my own Data Transfern Objects: http://martinfowler.com/eaaCatalog/dataTransferObject.htm. Not the ones generated by the framework – eviloop Jun 23 '15 at 21:01
  • NHibernate session is already meant to be used as a DAO – Vlad Jul 03 '15 at 14:07
  • right, but like all frameworks they do too much stuff - the problem that you described, correct ? - thus you need to an your own layer to restrict that and also map to the correct business model - remote facade above does that – eviloop Jul 03 '15 at 18:48
1

Your problem sounds like it is caused by a failure to follow the Interface Segregation Principle. Fortunately, there's a fairly simple solution: take your entity objects and create one interface in each for each type of client, containing only the methods that make sense for that client. Then, for each client, create a wrapper for your ORM that works using the appropriate interfaces for that client rather than the concrete entity classes. Finally, to combat the anaemic domain model problem identified above, you can start refactoring by moving methods that operate on entity interfaces from the client services into the entity itself.

Jules
  • 17,614
  • 2
  • 33
  • 63