I'm developing a system that has different types of users. Based upong their role, the system collects different information. I'm a little unsure how best to architect this.
At the base level I have a User entity which contains just the core info for a user. Beyond this, I need somewhere to store common information (not sure whether to add this to the User entity, create something like a Profile entity, or create a Member entity that extends the User entity).
After this, I then need somewhere to store the user type specific data. My roles are "Seller", "Merchant" and "Buyer". A User / Member can be one or more of these user types. I'm not sure here whether these should be seperate entities which extend the base User / Member, or whether these are more like extended profiles, which are a property on the User entity.
Could anybody sugest the best way to architect this?
Unless there's something fundamentally user-unrelated about the common information, you can store it into the user entity. For rôles, consider having separate entities linked to the user entity. This permits adding new rôles to a user (happens when somebody who has always been buying stuff suddenly decides to sell something), which the interface-based solution may have problems with (depending on your implementation language, of course).
An common pitfall is adding all rôle fields to the user entity. It works, but it tends to progress into unmaintainability as new rôles are added to the system.
I just finished creating something very similar for a system I'm working on. The theory, in general, is to separate the definition (who they are) of an entity from its behaviour (roles; what they do). I also wanted to preserve the ability to query users based on the metadata contained in the roles that they are assigned to.
I ended up creating a Person class that looks like this:
class Person {
Guid Id;
ISet<Role> Roles;
string Name; // and any other stuff a "person" might have
}
Next, I have an abstract Role class that looks like this:
abstract class Role {
Guid Id;
abstract string Name { get; } // implemented by concrete definitions of roles
Person Person;
}
From this, I derive individual classes that "define" each role I have in my system. A User role would look something like this:
class User : Role {
override string Name { get { return "User"; } }
string LoginId;
string Password;
// etc.
}
Rinse and repeat for any other roles you might have.
At the ORM level (where I use NHibernate), I define UserRole as a joined-subclass of the Role entity.
The underlying assumptions behind this approach are:
Roles aren't dynamic.
There is no definition of roles at the data layer. A role exists simply because there's a class that derives from it.
You can't assign a role to the same
person multiple times with different
metadata
Well, in theory, I guess you could but it makes no sense for my particular system for a person to have two User roles assigned to them with different login ids and passwords.
I would start by making a separate interface for each: IUser, IMember, ISeller, IMerchant and IBuyer. Then I would create a separate Class and for each interface, which understands how to handle the CRUD for the instance (Create, Read, Update and Delete).
The nexus is the member. The IMember interface needs methods/propreties for IsSeller, IsMerchant and IsBuyer. If those return TRUE, the you know you can cast the Member object into the corresponding interfaces, or at least fetch the interface handler via a method. Note that the Member object always supports the IUser interface too.
That should get your started.
Depends if the available roles are fixed or fluid. Sounds like they're fixed, so you can:
define user.role as an int.
Define the roles as static ints to the power of two, e.g. Role.SELLER=1, Role.MERCHANT=2, Role.BUYER=4, and so on.
Add a hasRole() method to the user object that does a simple bitwise OR operation to determine if a user has a particular role.
Related
I'm working on a Winforms project with sql server, splitted in several assemblies.
The first assembly Entities contains DTO like :
public class Attribution
{
public short UserId { get; set; }
public User User { get; set; }
}
public class User
{
public short Id { get; set; }
}
The second assembly Repository is accessing Sql Server database.
The third assembly Service is the link between previous.
There are other layers but this is not the point. I need of course DTO's everywhere in the app.
In sql server, Attribution.UserId and User.Id are the same datas, located in 2 separate tables, linked by Ìnner join.
Attribution.UserId must be public because I need access from Repository,Service, etc... But I don't need it in the "logical" part of the app, what I need is Attribution.User.
At this time I have a UserService class in which there is a GetUser() method and I call this method to get the user in my AttributionService.GetAttribution() method.
Is there a way to restrict access to Attribution.UserId property to Service assembly? Or is it a kind of "good practice violation" to query a User DTO in AttributionService class?
Many thanks for your recommandation.
`
One option would be to make the set of the property internal and the use the InternalsVisibleTo attribute to grant access to internals to the Repository assembly.
Another less technical and more logical option would be to make the setter private and let the only way for it to be modified be the classes constructor. That way, your repository can get users built, but nobody can modify the ID later.
As a last option you could create an interface that contains only what the non-repository classes should have access to and pass this around. I'm not a big fan because that means you have to cast it back to your concrete class in the repository and that basically means your repository is lying (saying it accepts an ISomething, but then throwing if the ISomething is not the exact, concrete Something it expects).
i am using LINQ to SQL, 3.5 Framework and i would like to know which is the best way to design the classes. Taking a very simple example of User table.
If i have a User table with 3 different roles of Customer, Admin, Cashier.
I would say i will need to create 3 classes for each of the role. e.g. customers.cs...
Question:
1) Since Linq .dbml already has the User auto generated from my user table, all the properties are already predefined, do i still need to create a User.cs class to be inherited by 3 of the classes role above? This is because i cannot add any duplicate properties in the User.cs e.g. Public string Name {get;set;} would failed because in the .dbml already has the property call Name.
2) This question will be very basic question i think... but i find it useful if i can know the correct answer. How should i park my functionality into the correct class? e.g. PrintYearlyReport(), CheckStaffSalary(), ModifySale(), UpdateGovernmentTax().... all of these functions are under the role of Admin. It will be very readable if we have admin.PrintYearlyReport(), admin.ModifySale()... However, if we park all the admin's functionalities in the Admin.cs file, then this file would be very very huge!!! For OOP sake, we need to have classes like e.g. Sale.cs, Payment.cs, Invoice.cs. If we split all those functionalities into each different classes, then we will no longer have the elegant way of calling the admin.PrintYearlyReport() anymore..
You can create sub-classes of the User class, i.e., Customer, Admin, and Cashier, then specify the correct class based on the user's role. Sometimes we design by creating a method like User.IsInRole or User.HasAccessTo methods that you can call to verify they can access or use certain functionality.
You can split the functionality into separate files but still have them in the same class by using partial classes. If you define public partial class Admin you can define the class Admin in as many separate files as you want, and all of the properties will be added together when building the project.
Let’s keep it simple. Usually the best answer is the simplest one. Do you need to have more than one class? May be may be not. If the differences between the roles is simple one liners, than why the need to create subclasses? I usually start out with one class and as the behavior is better defined and you can clearly diferentiate the subclasses than you create them. With that said you should think about what you want your objects to look like, and by that I mean what dependencies you what to create and what functionality will be shared. Composition vs inheretance When I think of users and roles I think: user has role x, not user is role x because roles can change. Common functionality and properties should be in a base class. May be you can put your access rules in a class that lives within the user:
User{
Name
Role
Rules{ }
}
So you can say
if(user123.Rules.CanPrint())
{
Print();
}
Create the rules inside the user and pass in the role(s) so the rules class can figure out what this user can do. This is how I would do it. My point is, don't get hungup on what class should go where. Define objects and behavior and let the classes define them selves. You will learn to spot when a class is getting too big and need to breake it up.
You can add stereotype to your class diagram and get live persistence annotations in your java code. If you use Hibernate then from your code you can get your database. No need to create an object UML model and another model for your database.
This is what I do and really cool !!
It only works with Java and not with c#.
i have got various custom datatypes in my web application to map some data from the database.
something like:
Person
Id
Name
Surname
and i need a List of persons in most of my application's pages
i was thinking to create a getter property that gets the list of persons from the database and store into cache in this way i do not have to call the database each time
something Like (pseudo code)
public List<Person> Persons
{
get { return if cache != null return List of Persons from cache else get from the database;}
}
Where shall i put this getter? in my Person class definition or into my base page( page from which all the others pages inherit)
Thanks
I think putting it in your base page would be better option.
Depending on your application architecture, putting process related code in your domain classes might be an issue. Some use it in DDD (domain-driven design) type applications though.
Better even, I usually try to hide those implementation details in a service class. You could have a PersonService class that would contain your above method and all person related operations. This way, any page requiring person information would simply call the PersonService; and you can concentrate your page code on GUI related code.
I don't think that you should put it in your Person class since it accesses the database and HttpContext.Current.Cache. Furthermore I think you should make it a method and not a property, to imply that this may be a "lengthy" operation. So, of the two options, I would put it on the base Page class.
I'm working on my first DDD project, and I think I understand the basic roles of entities, data access objects, and their relationship. I have a basic validation implementation that stores each validation rule with it's associated entity. This works fine for rules that apply to only the current entity, but falls apart when other data is needed. For example, if I have the restriction that a username must be unique, I would like the IsValid() call to return false when there is an existing user with the current name.
However, I'm not finding any clean way to keep this validation rule on the entity itself. I'd like to have an IsNameUnique function on the entity, but most of the solutions to do this would require me to inject a user data access object. Should this logic be in an external service? If so, how do I still keep the logic with the entity itself? Or is this something that should be outside of the user entity?
Thanks!
I like Samuel's response, but for the sake of simplicity, I would recommend implementing a Specification. You create a Specification that returns a boolean to see if an object meets certain criteria. Inject an IUserRepository into the Specification, check if a user already exists with that name, and return a boolean result.
public interface ISpecification<T>
{
bool IsSatisfiedBy(TEntity entity);
}
public class UniqueUsernameSpecification : ISpecification<User>
{
private readonly IUserRepository _userRepository;
public UniqueUsernameSpecification(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public bool IsSatisfiedBy(User user)
{
User foundUser = _userRepository.FindUserByUsername(user.Username);
return foundUser == null;
}
}
//App code
User newUser;
// ... registration stuff...
var userRepository = new UserRepository();
var uniqueUserSpec = new UniqueUsernameSpecification(userRepository);
if (uniqueUserSpec.IsSatisfiedBy(newUser))
{
// proceed
}
In DDD, there ia a concept called aggregate. It is basically responsible for consistency within the application.
IMHO, in this case specifically, I guess the CustomerRepository would be inside something like the "Customer aggregate", being the Customer class the aggregate root.
The root would then be responsible for doing all this stuff, and no one else could access the CustomerRepository options. And there are some possibilities:
The CustomerRepository could throw an exception if the name is not unique (and the Customer would catch and return the error, or something like that)
The CustomerRepository could have an IsValidUserName(), that the Customer would call before doing anything else
Any other option you can think of
I'm going to say that this is simply beyond the scope of DDD.
What you have with DDD is an aggregation of events that produce a useful model. However, data relationships between such models are not necessarily possible.
What consistency model are you using?
If you can commit multiple events in an ACID transaction you can ensure that changes to a group of aggregates happen atomically.
If you use an eventual consistency model you might not be able to actually validate these things until later. And when you do, you might need to compensate for things that have supposedly happened but are no longer valid.
Uniqueness must be answered within a context. If you model is small (in the thousands) you can have an aggregate represent the set of values that you want to be unique. Assuming a group aggregate transaction is possible.
If not, well, then you simply project your model to a database that support an uniqueness constraint. If this projection fails you have to go back to your aggregate and somehow mark it as invalid. All the while you need to consider failure. This is where a distributed long running process, like the saga pattern can be useful but also require that you think about additional things.
In summary, if you cannot use a storage model with a strong consistency guarantee everything becomes a lot more complicated. That said, there are good, well through out patterns for managing failures in a distributed environment but it turns the problem on it's head a bit because now you need to consider failure, at every point along the way, which is a good thing but it will require a bigger time investment.
I find it difficult to determine the responsiblity of classes: do i have to put this method in this class or should I put this method in another class? For example, imagine a simple User class with an id, forname, lastname and password. Now you have an userId and you want the forname and lastname, so you create a method like: public User GetUserById(int id){}. Next you want to show list of all the users, so you create another method: public List GetAllUsers(){}. And offcourse you want to update, delete and save a user. This gives us 5 methods:
public bool SaveUser(User user);
public bool UpdateUser(User user);
public bool DeleteUser(User user);
public User GetUserById(int id);
public List<User> GetAllUsers();
So my question is: do you put all these methods in the User class? Or do you create another data class (UserData class) which may connect to the database and contain all these methods?
What you are describing here is basically a choice between the Active Record Pattern or the Repository Pattern. I'd advise you to read up on those patterns and choose whichever one fits your application / experience / toolset.
I would not put those specific methods into the 'User' class.
There are 2 common approaches for this 'problem':
You put those method in the User
class, and then this means you 're
using the Active Record pattern
You put those methods in a
separate class (UserRepository) for
instance, and then you're using the
Repository pattern.
I prefer the repository-approach, since that keeps my 'User' class clean, and doesn't clutter it with data access code.
Barring additional complexity specific to a group of users (or really elaborate database access mechanics) I might make those methods static on the User class.
Those methods sound more like a UserManager (or something like that) to me. The user class should correspond to and represent only a single user, not many.
If we look at Enterprise Application design patterns, then the methods for fetching Users i.e. GetUserByID and GetAllUsers would be in separate class - you can name it UserData or UserDAO (DAO - Data Access Object).
Infact you should design an interface for UserDAO with appropriate methods for handling User Objects - such as CreateUser, UpdateUser, DeleterUser, GetUserXXX and so on.
There should be an implementation of UserDAO as per the data source, for example if your users are stored in database then you can implement the logic of accessing database in the implementation of UserDAO.
Following are the advantages of keeping the access methods in separate class:
1) User object should be plain object with just getter setter methods, this would facilitate passing object across tiers - from data access tier, to business tier to web tier. This would also help keep User Object serializable
2) The data access logic is loosely coupled from the User object - that means if the datasource changes, then you need not change the User object itself. This also assists in Test Driven Development where you might need to have mock objects during testing phase
3) If User object is complex object with relations with other objects such as Address or Department or Role etc. then the complexity of relationships will be encapsulated in UserDAO rather than leaking in the User Object.
4) Porting to frameworks like NHibernate or Spring.NET or .NET LINQ would become easier if the patterns are followed
Lets us see you scenario as this.
There are 'N' number of people working in assembly division of you company.
It is okay to go to a person and ask about his information BUT you cant expect him to tell you details of all persons working in assembly division. Reason why shud he remember all the details and if you do expect then his effeciency will go down(work on assembly and also remember details of others).
So ..... perhaps we can appoint a manager who can do this ppl maanagement activities
(get details, add new person, edit ,delete etc etc )
Therefore you have two entities
1) User/Person working in your assembly deivision
2) a Manager
Thus two classes. Hopes this will help you.
Thanks
If I understand your question correctly the User class deals with a single user. Hence the user class does not have a clue about how many users there are or anything about them. The structure holding this information is somewhere else and the methods you mention seem to belong to that structure / class.
With all else being equal either way is fine. Which to choose, though, usually depends on the overall architecture of the application or class library in which you find the User class. If the data access code seems tangled with the User object code, then it might make more sense to split it into two classes as you've considered. If the CRUD methods are one-line delegations to a DAL with maybe application-specific logic, then leaving them in the User class should be okay.
The complexity is more or less the same in both cases—it's a trade-off between a low-maintenace assembly with few high-maintenance classes or a high-maintenance assembly with a larger number of low-maintenance classes.
I'm also assuming that the CRUD methods should be static.
Do what's easiest to get the code written right now but consider possible refactorings in the future should you find that it'll be better that way.