In [this post], I'm struggling to implement a State Pattern as #jonp suggests. I don't quite get how to use what's he's posted but it leads to the thought that maybe I'm trying to fit a square peg into a round hole. So my question:
If I have a visitor to my site that can play multiple roles i.e. a User could be a Vendor, an Employer, an Advertiser, OR all of the above, should I be using inheritance? I've declared:
class Vendor : User {}
class Advertiser : User {}
et cetera, but when a user is both a vendor and an employer then instances of different classes really point to the same underlying object... I'm not sure this can work. How do I model it?
* update *
thanks everyone (you all get a point (it's all I can give)). I've been pulling my hair out over deep-copies with EF, downcasting and the state pattern for the last several days. The role approach makes much more sense.
This sounds like a situation to which the attribute pattern (or so I call it) would be very appropriate. It's a much more loosely-coupled approach than simple inheritance that can be used to specify multiple "behaviours" or in your case kinds of User. It's really nothing more complicated than an object having tags of another kind of object.
The easiest way to implement it would be to have a concrete User class, with a read-only property IList<UserRole> (internally this can be a List<T> field perhaps). Your UserRole class would then be abstract, and VendorRole/AdvertiserRole/etc. would derive from it, allowing you to tag on an arbitrary number of different roles (even ones of the same type) onto a given user. These roles can in addition define their own custom behaviours, utility methods, etc.
In addition, you could define a GetRole<TRole> method on your User class to facilitate access to roles of a specific type (assuming each User only has a single Role of a specific subtype).
Side note: you may also consider the decorator patern, which is closely related to the above mentioned pattern -- though personally I feel it is overkill here, and really adds nothing in terms of flexibility or power. It often just obscures what you're trying to do; though feel free to investigate anyway.
You should favor Composition over Inheritance if the different roles have to contain different logic that would be implemented using polymorphism and abstract methods, for example:
public class User
{
public Role Role { get; set; }
}
public abstract class Role
{
abstract void DoRoleSpecificStuff();
}
public class Vendor : Role
{
public void DoRoleSpecificStuff()
{
/* ... */
}
}
public class Employer : Role
{
public void DoRoleSpecificStuff()
{
/* ... */
}
}
public class Advertiser : Role
{
public void DoRoleSpecificStuff()
{
/* ... */
}
}
If a User can have multiple Roles, consider using a Roles collection property:
public IEnumerable<Role> Roles { get; set; }
Otherwise, an enumeration using the [Flags] attribute could be fine, too, depending on whether you need to be able to assign multiple Roles:
public class User
{
public Roles Roles { get; set; }
}
[Flags]
public enum Roles
{
Advertiser = 0x0,
Employer = 0x1,
Vendor = 0x2
}
You would assign a combination of different roles as follows:
User user = new User
{
Roles = Roles.Advertiser | Roles.Vendor;
};
That would make the User both an Advertiser and a Vendor, but not an Employer.
“I'm a * but I'm also a **” is known as Multiple Inheritance. C# does not support this, so you shouldn't be considering it.
It's indeed composition over inheritance here, but it's more like this if a single user can have multiple roles.
If there are relatively few roles, a 'parking lot' analogous to an outer join result may work. In this pattern, no Role base class is required.
class User
{
// all of these may be null if not applicable
VendorRole VendorRole { get; set; }
EmployeeRole EmployeeRole { get; set; }
AdvertiserRole AdvertiserRole { get; set; }
}
If a user may have multiple instances of a single role, a collection pops up:
class User
{
// all of these may be null if not applicable
VendorRole VendorRole { get; set; }
EmployeeRole EmployeeRole { get; set; }
ICollection<AdvertiserRole> AdvertiserRoles { get; }
}
Alternatively, if there may be a messy pile of roles, if roles get added dynamically, or what have you, you'll need a collection and a base type. If Entity Framework is involved, though, dynamically added roles seem unlikely to me.
class User
{
ICollection<Role> Roles;
}
Related
I am using class inheritance to add a set of basic fields that all my entities must include. When I do this, EF Core honors any data annotations that exist in the base class, such as [TimeStamp], on the class that is inheriting from it:
public class SomeClass : BaseEntity
{
public string SomeEntityField { get; set; }
}
public class BaseEntity
{
public int Id { get; set; }
public DateTimeOffset UpdatedDate { get; set; }
public DateTimeOffset CreatedDate { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
The above is great when I want to add all inherited fields.
But, what if I wanted to to be able to create a field definition ONCE, and then use that definition in just a few other entities whilst also inheriting from the base class (above) at the same time?
Lets suppose I have this entity, ItemType:
public class ItemType : BaseEntity
{
[StringLength(28)]
public string ItemTypeId { get; set; }
...
I'd like to be able to define the field ItemTypeId in one place, and then use it on multiple entities including the above table WITHOUT having to manually add/maintain the annotation(s) in all those entities. For example, if I need to make the field wider like [StringLength(50)], I adjust it in one place and then all associated fields are updated on the next migration since they all "read" from the same definition. I've tried
using interfaces, but data annotations on interfaces are not honored by EF.
multiple inheritance, but that can't be used because I may need multiple "one-off" fields (and interfaces don't work as per #1)
According to CS1721 nothing will work (ok, with the exception of the single base class itself).
I think ideally I'd like to be able to define the entity fields in CommonFieldType as in the code below, and then have target entities inherit from them, but unfortunately that can't work for the reasons above.
namespace RDCApp.Shared.CommonFieldType
{
public abstract class ItemTypeIdCFT
{
[StringLength(28)]
public string ItemTypeId { get; set; }
}
public abstract class AnotherCFT
{
[StringLength(100)]
public string AnotherField { get; set; }
}
...
I can't be the only person who needs/would like this so is there another way?
I am aware that the Fluent API could be used, but my project is so invested in data annotations that using that (as well as) feels wrong, and means I have 2 places to look in and define field attributes against. Defining against the POCOs directly just feels right to me!
EDIT
To qualify what "feels right to me" means: my VS solution includes both the server (ASP.NET Core) and client side (Blazor WASM) projects. Both tiers can 'see' the entities/POCOs in a shared project and both tiers need to know what the annotations are to perform validation. This means I only need to define validation/attributes once and in turn both tiers have sight of that.
For me, Fluent is not a suitable option - though if this were a typical server side only App I'd shoot for Fluent.
You could define an interface and a generic fluent api helper method to define the fields.
public interface IHasItemType{
int ItemTypeId { get; set; }
}
public void DefineItemType<T> (EntityTypeBuilder<T> builder) where T:IHasItemType{
builder.Property(i => i.ItemTypeId) ...
}
Or you could apply conventions in OnModelCreating
foreach (var table in modelBuilder.Model.GetEntityTypes())
{
foreach (var column in table.GetProperties())
{
// ...
}
}
Fluent API was not suitable for my project need.
Custom annotations would work great for validation logic on both tiers, but unfortunatley DB schema definitions like [StringLength(30)] can't work (or at least I couldn't get to that).
So I landed on a workaround and although I'm not in love with it, it is serviceable for my specific need:
First, I define a particular fields attributes as constants:
public class FieldAttributeValues
{
public const string InventSerialIdComment = "Unique Id of the asset";
public const int InventSerialIdStringLength = 25;
public const bool InventSerialIdRequired = true;
...
}
Then, those constants can be used inside data annotations, for example:
public class SpecAttribute : BaseEntity
{
[Required(AllowEmptyStrings = FieldAttributeValues.InventSerialIdRequired)]
[StringLength(FieldAttributeValues.InventSerialIdStringLength)]
[Comment(FieldAttributeValues.InventSerialIdComment)]
public string InventSerialId { get; set; }
...
}
The downside to this approach is that the developer has to consciously check the FieldAttributeValues class for defined values for a particular field (sort of a manual convention process I guess).
The upshot is that the developer isn't implicity forced to use all of the attributes or even the attribute values as defined, since not all entities will always require the same setup across the patch - i.e. [Required(true)] might generally hold true for most entities, but not some other edge case entity.
I have the following interface:
public interface IValidator
{
// Checks whether the selected roles are Valid based on Buisness rules for the
// specific EntityValidator
bool HasCompleteValidSelection(
ICollection<Role> availableRoles, ICollection<Role> selectedRoles);
//Checks whether the available roles are Valid for the specific entity
bool HasValidRoles(ICollection<Role> availableRolesList);
//Computes the Remaining Roles that needs to be selected to make it a Valid selection
ICollection<Role> GetRemainingRoles(
ICollection<Role> availableRoles, ICollection<Role> selectedRoles);
}
Now, I have bunch of EntityTypes,mentioned in the enum:
public enum EntityType
{
Shop= 1,
SmallBuisness= 2,
Corporation = 3,
Firm = 4,
Partnership = 5,
Unknown = 0
}
All the above Entity Types have their corresponding validator classes which implements the IValidator.
public class ShopValidator : IValidator
{
public bool HasCompleteValidSelection(
ICollection<Role> availableRoles, ICollection<Role> selectedRoles)
{ /*implementation */ }
public bool HasValidRoles(ICollection<Role> availableRolesList)
{ /*implementation */ }
public ICollection<Role> GetRemainingRoles(
ICollection<Role> availableRoles, ICollection<Role> selectedRoles)
{ /*implementation */ }
}
But the concern is some of the validator classes are having exact same logic/code.
What I have thought of is:
Instead of Interface, created abstract class and kept the common
code there
Validator classes, which has different implementation,are
overriding the abstract class.
Now, my questions are:
Although the above is working fine, is there any better
approach/design pattern more suitable for the above scenario?
I am using Autofac like below, its working fine, but is there any
issue that you can foresee?
builder.RegisterType().As().Keyed(EntityType.Shop);
// other validators similarly.
Personally, I like your initial proposal. Some will probably disagree, but I like the symmetry of creating a class for each entity type, even if some of those classes have no code.
That is, if there is some common code, I would use your suggestion of converting the interface to a base class and put your common code there. (Much like CException.)
Of course, if the common code is more complex, then you might have more specialized base classes that your final class can derive from, but in that case it isn't near as elegant.
I am developing a application for sports clubs administraion. And my problem is that I have one primary class Member which contains all the "default" information (name, surname, gender...) and two other classes Coach and Practitioner which inherit from Member. A coach has some specific properties (salary, trainings held in current month...) wheres a practitioner has some others (isCompetitor, category ...)
The problem is that a Practitoner can also be a Trainer as well as the other way around. How can I model this into something that is better then having two entries for the same person?
Edit: this is how it looks now
Class Member {}
Class Coach:Member {}
Class Practitioner:Member {}
You can create one class 'member' that contains a list of roles. Each role (coach and/or practitioner) inherit from a base class 'role' which contains all properties you now have in your member class. Coach and practitioner than have their own specific properties. So:
public class Member {
public IList<Role> Roles { get; private set; }
public Member(){
Roles = new List<Role>();
}
}
public class Role {
public string SomeGlobalProperty { get; set; }
}
public class Coach : Role {
public string SomeSpecificProperty { get; set; }
}
public class Practitioner : Role {
public string SomeSpecificProperty { get; set; }
}
If you're only looking at them in one way at a time - so as one of a group of practitioners, or as one of a group of trainers - then you can create them as the specific type of member they are being viewed as at a time. If required, you can add a boolean property "IsTrainer" to practitioner and "IsPractitioner" to trainer, to indicate that there is more info about that person elsewhere.
This presumes you're only looking at them in one way at a time, and not getting a page with all info about the person.
SImeple: Realize that you basiaclly need to read an intro book into OOP.
A Member is a Member (and even that is disputable - acutally it is a Party, regardless of what it does).
It has different roles which are basically a collection of roles, all with start and end date.
Party
CoachInformation
PractitionerInformation
etc.
I suggest reading "The Data Model Resource Book", volume 1 - they go into great detail about this standard problem and how most people get it wrong.
Assuming the following domain entity :
public enum Role
{
User = 0,
Moderator = 1,
Administrator = 2
}
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public Role Role { get; set; }
}
I need to know if the user can perform "Edit" action. So i've 2 solutions :
Create a CanEdit method inside the User entity
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public Role Role { get; set; }
public bool CanEdit()
{
return Role == Role.Moderator || Role == Role.Administrator;
}
}
Create a CanEdit Extension Method for User type :
public static class UserExtensions
{
public static bool CanEdit(this User user)
{
return user.Role == Role.Moderator || user.Role == Role.Administrator;
}
}
Both solution works, but the question is WHEN use standard methods vs using Extensions methods ?
Extension methods are simply syntactic sugar for plain, ordinary static methods.
If you control the class structure, you should implement all the necessary functionality within the class. Where extension methods are really useful/necessary is if you don't own the class that you are trying to "extend."
For this example, I think you should put the logic inside the User class. It is a logical function of the user itself; consumers should be able to use the CanEdit() method without having to use or even know about the UserExtensions class.
I mostly agree with Aaronaught's answer, but consider this:
Maybe your CanEdit() method or other similar methods (business rules) might change more or less often or depend on some external factors. Or over time, you will have more and more such rules (for different concerns). In that case you might want to keep them in a different place, separated from the domain model to ensure that the domain model doesn't have too many different responsibilities and doesn't need to change very often.
Then, one way can be to implement them as extension methods, because this allows you to keep these business rules separate from your domain model (e.g. User class), but the method is still easily discoverable by users of the User class.
Another way to implement such business rules would be the specification pattern, where you implement each rule as a separate (specification-) class, e.g. demonstrated in this blog post.
There is very little point in using Extension methods for the sake of using them. If the method belongs to the class, use it there. Extension methods are for extending things, use them when you have no control over the class, or for giving functionality to an interface where the functionality should apply to all classes derived from that interface.
if you do not have direct access to the source code for the class you should use Extensions methods if you do have access to the source code i see no reason to not use a standard methods...
I agree with Aaronaught here: Implement your own logic the old-fashioned way. Static method might cause issues (missing using statement and the method seems to be "missing") lateron.
Something inherent to your model should be part of your classes.
UPDATE:
So pretty much everyone here has told me that I just need to start all over again on how I designed my classes (thank you folks for your excellent answers by the way!). Taking the hint, I started doing extensive reading on the strategy pattern. I want to create behavior classes (or strategy classes) that inherit from an abstract base class or classes. The Candidate class would then have properties w/ the different abstract base class/classes as the Type for the behaviors or strategies. maybe something like this:
public abstract class SalaryStrategy {
public abstract decimal Salary { get; set; }
public abstract decimal Min { get; set; }
public abstract decimal Mid { get; set; }
public decimal CompaRatio {
get {
if (this.Mid == 0) { return 0; }
else { return this.Salary / this.Mid; }
}
}
}
public class InternalCurrentSalaryStrategy {
public override decimal Salary { get; set; }
public override decimal Min {
get { return this.Salary * .25m; }
set { }
}
public override decimal Mid { get; set; }
}
public class Candidate {
public int Id { get; set; }
public string Name { get; set; }
public SalaryStrategy CurrentSalaryStrategy { get; set; }
}
public static void Main(string[] args) {
var internal = new Candidate();
internal.CurrentSalaryStrategy = new InternalCurrentSalaryStrategy();
var internalElp = new Candidate();
internalElp.CurrentSalaryStrategy = new InternalCurrentSalaryStrategy();
var elp = new Candidate();
// elp.CurrentSalaryStrategy can stay null cause it's not used for elps
}
Any comments or suggestions?
ORIGINAL Question:
I am trying to learn and become more proficient at design patterns and principles. I have am currently working on a design for few classes that has stumped me. Here's a very condensed version of the code:
public class Candidate {
public int Id { get; set; }
public string Comments { get; set; }
// lots more properties and behaviors...
}
public class InternalCandidate : Candidate {
public decimal CurrentMid { get; set; }
public decimal CurrentMax {
get { return this.CurrentMin * 1.3m;
}
// lots more properties and behaviors...
}
public class EntryLevelCandidate : Candidate {
public string Gpa { get; set; }
// lots more properties and behaviors...
}
public class InternalEntryLevelCandidate /* what do I inherit here??? */ {
// needs all of the properties and behaviors of
// EntryLevelCandidate but also needs the CurrentMin and
// CurrentMax (and possibly more) in InternalCandidate
}
The InternalEntryLevelCandidate class is primarily an EntryLevelCandidate but needs to share some of the implementations of InternalCandidate. I say implementations because I don't want the implementations to be different or repeated, otherwise I would use an interface for common contracts and have concrete implementations in each class. Some of the implementations of the InternalCandidate properties and behaviors need to be common or shared. I have read about C++ and Ruby mixins, which seem to be something similar to what I want to do. I also read this interesting blog post that discusses an idea for a behavior type where a class would be able to inherit multiple behaviors while still maintaining a single "is a" relationship: http://www.deftflux.net/blog/post/A-good-design-for-multiple-implementation-inheritance.aspx. This seems to convey what I am wanting. Can anyone give me some direction on how I can accomplish this using good design practices?
Immutable data value classes. If any properties in your various Candidate subclasses represent some kind of meaningful data value, create an immutable class for it, with the behaviors you need. Each of your distinct Candidate subclasses can then use the data type, but your code is still encapsulated in the data classes.
Extension methods. These could be overloaded to work with any classes.
I'd avoid the decorator pattern and stick with compiled/reflectable functionality.
Composition. Develop the unique behaviors in separate classes right away, and build your Candidate classes around them, rather than writing unique behaviors in your Candidate classes and trying to pull out their functionality for use in related classes later.
Depending on how you use the classes, you could also implement and make use of explicit and implicit conversion operators to a related type, so instead of reimplementing interfaces (which you wanted to avoid), you could actually cast your object into the type/implementation you need for whatever purpose.
Another thing I just thought of, related to that last paragraph, is to have a leasing system, where your class spawns and object of the appropriate type, allows it to be manipulated, then consumes it later to assimilate the updated information.
Here's a scholarly paper on the subject that I think is pretty interesting (PDF link).
But, I think you are trying to impose business logic in your generalizations. You happen to know that an InternalCandidate will never have his GPA looked at. But, an InternalCandidate certainly has a GPA. So, you have cracked out this strange guy called an InternalEntryLevelCandidate because you happen to know that you want to look at this guy's GPA. Architecturally, I think the EntryLevelCandidate is incorrect. I would add a "Level" concept to a Candidate and give him a GPA. It's up to the business logic to decide if they look at the GPA or not.
Edit: Also, Scott Meyers does a great job of dissecting this issue in his books.
Disclaimer:
In my experience needing multiple inheritance is the exception rather than the rule, careful design of class hierarchies can usually avoid needing this feature. I agree with JP that this requirement could be avoided in your sample.
Back to the question, there is no clean solution, however you have a few options:
Use extension methods, has the disadvantage that right click Resolve does not works, also some people really dislike these puppies.
Create an aggregate object that holds and instance of each class you want composited, re-implement stub methods that delegate.
Define an interface for each behavior and have the methods in the base check if this is IInterface before executing the behavior. (allows you to pull behavior definitions to the base)
Near duplicate:
Multiple inheritance in C#
I agree that inheritance doesn't seem to be the right thing here. I'm not sure that I know the perfect answer, but perhaps the Decorator pattern is appropriate.
Another, more esoteric idea is to think about aspect-oriented programming. You can do some pretty amazing things with aspects, but it's a very advanced topic that I still haven't mastered. The kind of folks who have are like Rikard Oberg and his Qi4J cohorts.
I'd just use the Delegation pattern. Ultimately I'd use an interface for each distinct piece of functionality, then have a concrete class as a delegate for each interface. Then your final classes just use the delegates they need and can inherit from multiple interfaces.
public class InternalEntryLevelCandidate : EntryLevelCandidate {
private InternalCandidate internalCandidateDelegate
= new InternalCandidate();
public decimal CurrentMid {
get { return internalCandidateDelegate.CurrentMid; }
set { internalCandidateDelegate.CurrentMid = value; }
}
public decimal CurrentMax {
get { return internalCandidateDelegate.CurrentMax }
}
}