Tło:
Projektuję aplikację serwera i tworzę osobne biblioteki DLL dla różnych podsystemów. Dla uproszczenia załóżmy, że mam dwa podsystemy: 1) Users
2)Projects
Publiczny interfejs użytkownika ma metodę taką jak:
IEnumerable<User> GetUser(int id);
A publiczny interfejs projektów ma metodę taką jak:
IEnumerable<User> GetProjectUsers(int projectId);
Na przykład, kiedy musimy wyświetlić użytkowników dla określonego projektu, możemy zadzwonić GetProjectUsers
, co da obiekty z wystarczającą ilością informacji do wyświetlenia w siatce danych lub podobnej.
Problem:
Idealnie, Projects
podsystem nie powinien również przechowywać informacji o użytkownikach i powinien po prostu przechowywać identyfikatory użytkowników uczestniczących w projekcie. Aby służyć GetProjectUsers
, musi wywołać GetUser
w Users
systemie dla każdego identyfikatora użytkownika przechowywane we własnej bazie danych. Wymaga to jednak wielu osobnych GetUser
wywołań, powodując wiele osobnych zapytań SQL w User
podsystemie. Tak naprawdę nie testowałem tego, ale ten gadatliwy projekt wpłynie na skalowalność systemu.
Jeśli odłożyłbym na bok separację podsystemów, mógłbym przechowywać wszystkie informacje w jednym schemacie dostępnym dla obu systemów i Projects
po prostu zrobić, JOIN
aby uzyskać wszystkich użytkowników projektu w jednym zapytaniu. Projects
musiałby także wiedzieć, jak generować User
obiekty z wyników zapytania. Ale to łamie separację, która ma wiele zalet.
Pytanie:
Czy ktoś może zasugerować sposób na zachowanie separacji przy jednoczesnym unikaniu wszystkich tych indywidualnych GetUser
połączeń podczas GetProjectUsers
?
Na przykład, pomyślałem, że miałem dla użytkowników, aby dać systemom zewnętrznym możliwość „otagowania” użytkowników parą wartość-etykieta oraz żądania użytkowników o określonej wartości, np .:
void AddUserTag(int userId, string tag, string value);
IEnumerable<User> GetUsersByTag(string tag, string value);
Następnie system Projekty mógłby oznaczyć każdego użytkownika dodawanym do projektu:
AddUserTag(userId,"project id", myProjectId.ToString());
a podczas GetProjectUsers może poprosić wszystkich użytkowników projektu w jednym wywołaniu:
var projectUsers = usersService.GetUsersByTag("project id", myProjectId.ToString());
część, której nie jestem pewien, to: tak, użytkownicy są agnostycy projektów, ale tak naprawdę informacje o członkostwie projektu są przechowywane w systemie użytkowników, a nie projektów. Po prostu nie czuję się naturalnie, więc próbuję ustalić, czy brakuje mi tutaj dużej wady.
źródło
GetUser
zamiast zapytania do bazy danych, zajrzy do pamięci podręcznej. Oznacza to, że tak naprawdę nie ma znaczenia, ile razy zadzwoniszGetUser
, ponieważ ładuje dane z pamięci zamiast z bazy danych (chyba że pamięć podręczna została unieważniona).select
zapytań dziennie, lepiej skorzystaj z buforowania. Z drugiej strony, jeśli dodajesz miliardy jednostek do bazy danych, ale otrzymujesz tylko kilka tysięcyselect
sz bardzo selektywnymiwhere
s, buforowanie może nie być tak przydatne.