Background:
I am designing a server application and creating separate dll's for different subsystems. To simplify things, let's say I have two subsystems: 1) Users
2) Projects
Users's public interface has a method like:
IEnumerable<User> GetUser(int id);
And Projects's public interface has a method like:
IEnumerable<User> GetProjectUsers(int projectId);
So, for example, when we need to display the users for a certain project, we can call GetProjectUsers
and that will give back objects with sufficient info to show in a datagrid or similar.
Problem:
Ideally, the Projects
subsystem shouldn't also store user info and it should just store Ids of the users participating in a project. In order to serve the GetProjectUsers
, it needs to call GetUser
of the Users
system for each user id stored in its own database. However, this requires a lot of separate GetUser
calls, causing a lot of separate sql queries inside the User
subsystem. I haven't really tested this but having this chatty design will affect the scalability of the system.
If I put aside the separation of the subsystems, I could store all info in a single schema accessable by both systems and Projects
could simply do a JOIN
to get all project users in a single query. Projects
would also need to know how to generate User
objects from the query results. But this breaks the separation which has many advantages.
Question:
Can anyone suggest a way to keep the separation while avoiding all these individual GetUser
calls during GetProjectUsers
?
For example, one I idea I had was for Users to give external systems the ability to "tag" users with a label-value pair, and to request users with a certain value, e.g.:
void AddUserTag(int userId, string tag, string value);
IEnumerable<User> GetUsersByTag(string tag, string value);
Then the Projects system could tag each user as they are added to the project:
AddUserTag(userId,"project id", myProjectId.ToString());
and during GetProjectUsers, it could request all the project users in a single call:
var projectUsers = usersService.GetUsersByTag("project id", myProjectId.ToString());
the part I'm not sure about this is: yes, Users is agnostic of projects but really the information about project membership is stored in the Users system, not Projects. I just doesn't feel natural so I'm trying to determine if there's a big disadvantage here that I'm missing.