Clean smaller Objects - oop

Trying to break up a large aggregate root and just want some help to see if I'm doing it correctly
Consider the following aggregate root "Team" which looks like the following
public class Team : IAggregateRoot
{
public List<Player> Players {get; set;}
// Lots of other properties
public void AddPlayer(Player player){}
public void RemovePlayer(string playerId){}
public void MakePlayerCaptain(string playerId){}
// More Methods
}
So to break that up and make the Team class smaller, I create a new class called Roster
public class Roster
{
public List<Player> Players {get; set;}
public void AddPlayer(Player player){}
public void RemovePlayer(string playerId){}
public void MakePlayerCaptain(string playerId){}
}
And Team now becomes
public class Team : IAggregateRoot
{
public Roster Roster {get; set;}
// Lots of other properties
// More Methods
}
which makes Team smaller and gives me more cohesive models.
But this causes me to peek into the team aggregate root to access roster and make changes. i.e
team.Roster.MakePlayerCaptain()
Or I would just add the methods back onto team and they then call roster object? But then I'm back to having lots of methods (but smaller I guess) in my Team object.
What is the cleanest approach to take with this kind of thing or can anyone link me to some reading around this?

I'm not an expert, but I think the best thing to do in terms of defensive programming would be to have a method in Team that calls the Roster... Roster could even be a subclass of Team if you have some REALLY defensive programming involved.
Team class:
public class Team : IAggregateRoot
{
private Roster roster {get; set;} // Now private
public void AddPlayer(Player player){roster.AddPlayer(player)} // call roster.AddPlayer() and do other stuff if you need to
public void RemovePlayer(string playerId){roster.removePlayer(playerId)} // call roster.RemovePlayer() and do other stuff if you need to
public void MakePlayerCaptain(string playerId){roster.MakePlayerCaptain(playerId)} // call roster.MakePlayerCaptain() and do other stuff if you need to
private class Roster // Now a subclass of Team for defensive programming, assuming it will not be used outside of Team class
{
public List<Player> Players {get; set;}
public void AddPlayer(Player player){}
public void RemovePlayer(string playerId){}
public void MakePlayerCaptain(string playerId){}
}
}

Related

Cannot create a DbSet for 'Model' because this type is not included in the model for the context

I do a Generic and using DI
so I create a empty class
public class DBRepo
{
}
and my model class to inheriting class DBRepo
public partial class UserAccount : DBRepo
{
public int Id { get; set; }
public string Account { get; set; }
public string Pwd { get; set; }
}
then this is a Interface to do CRUD
public interface IDBAction<TEntity> where TEntity : class,new()
{
void UpdateData(TEntity _entity);
void GetAllData(TEntity _entity);
}
public class DBService<TEntity> : IDBAction<TEntity> where TEntity : class,new()
{
private readonly CoreContext _db;
public DBService(CoreContext _db)
{
this._db = _db;
}
public void UpdateData(TEntity _entity)
{
this._db.Set<TEntity>().UpdateRange(_entity);
this._db.SaveChanges();
}
public void GetAllData(TEntity _entity)
{
var x = this._db.Set<TEntity>().Select(o => o).ToList();
}
}
And I Dependency Injection Service Provider in constructor
this.DBProvider = new ServiceCollection()
.AddScoped<IDBAction<DBRepo>, DBService<DBRepo>>()
.AddScoped<DBContext>()
.AddDbContext<CoreContext>(options => options.UseSqlServer(ConnectionString))
.BuildServiceProvider();
last step I Get Services
DBProvider.GetService<IDBAction<DBRepo>>().GetAllData(new UserAccount());
I will get a error message same with title
or I change to
DBProvider.GetService<IDBAction<UserAccount>>().GetAllData(new UserAccount());
I'll get other message
Object reference not set to an instance of an object.'
but the void UpdateData() is can work,
so how to fix GetAllData() problem?
The error simply is because the class you're using here UserAccount has apparently not been added to your context, CoreContext. There should be a property there like:
public DbSet<UserAccount> UserAccounts { get; set; }
Regardless of whether you end up using the generic Set<T> accessor, you still must defined a DbSet for the entity on your context.
That said, you should absolutely not be creating your own service collection inside your repo. Register your context and your repo with the main service collection in Startup.cs and then simply inject your repo where you need it. The DI framework will take care of instantiating it with your context, as long as you have a constructor that takes your context (which you seem to).
And that said, you should ditch the repo entirely. It still requires a dependency on Entity Framework and doesn't do anything but proxy to Entity Framework methods. This is just an extra thing you have to maintain and test with no added benefit.

abstract class methods overriding the methods of another abstract class

Lets say that I have this line of code:
public abstract class User
{
public string name;
public string email;
public string password;
public abstract void Create();
public abstract void Remove();
public abstract void Modify();
}
And then another abstract class:
public abstract class AbstractCustomer : User
{
public string address;
public Order order;
public abstract override void Create(string n,string e,string pa,int ph,string a);
public abstract override void Modify(string e, string pa, int ph, string a);
public abstract override void Remove(Order o);
public abstract void PlaceOrder(Item i);
public abstract void MakePayment(Order o);
}
and we have the customer which implements the AbstractCustomer:
public class Customer : AbstractCustomer
{
public override void Create(string name, string email, string password, int phoneNum, string address)
{
this.name = name;
this.email = email;
this.password = password;
this.phoneNum = phoneNum;
this.address = address;
this.isActive = true;
ConnectionToDB.SaveCustToDB();
}
public override void Remove(Order order)
{
order.CancelOrder();
}
public override void Modify(string email, string password, int phoneNum, string address)
{
ConnectionToDB.UpdateCustInDB();
}
public override void PlaceOrder(Item item)
{
order = new Order(item);
}
public override void MakePayment(Order order)
{
ConnectionToDB.SavePayToDB(order);
}
}
and this is where the problem starts (this is a helper class whose purpose is to call the methods easily)
public static void Create(AbstractCustomer user, string name, string email, string password, int phoneNum, string address)
{
user.Create(name, email, password, phoneNum, address);
}
public static void Remove(AbstractCustomer user, Order order)
{
user.Remove(order);
}
public static void Modify(AbstractCustomer user, string email, string password, int phoneNum, string address)
{
user.Modify(email, password, phoneNum, address);
}
public static void PlaceOrder(AbstractCustomer user, Item item)
{
user.PlaceOrder(item);
}
public static void MakePayment(AbstractCustomer user, Order order)
{
user.MakePayment(order);
}
These lines of codes produces errors like:
VS will tell you that the Customer class didn't implement the User's abstract methods(well, I think I did because I tried overriding it in the AbstractCustomer). But apparently, we don't need to override it in the Abstract class because the child class(Customer) will automatically inherits it and from there you can just directly override the methods. I found the explanation here overriding abstract methods in an inherited abstract class
But by doing the above solution, it presents another problem. The AbstractCustomer class will lose its purpose and therefore the HelperClass can't call any methods because its static classes depends on the AbstractCustomer that will be passed in the method.
So for the questions: (Problem: Grouping the methods into a static class for me to call it easily)
Is there a way to fix this kind of problem?(I'm thinking of using decorator pattern)
If I use the decorator pattern, what is the purpose of the ConcreteComponent?Is it okay if I remove it?
If I don't use the decorator pattern, is there any pattern available for this kind of problem?
If I don't use any pattern, is there any way to solve this?
Thanks for reading! Sorry coz its a long one! :)
Your solution is not related to Decorator pattern. Decorator - it is something, that should be inherited from existing abstraction (AbstractCustomer in your case) and add extra logic to it (it can be logging, or it can be extra check of each method's parameters for null, or something like that...). See this link.
Btw, I don't like the way how you construct your abstractions. It is better to have well-grained interfaces for each of your methods, e.g. ICanCreate for Create() method, ICanRemove for Remove() method, etc. It allows you to control further types which will implement that functionality. E.g., one customer can implement only ICanCreate interface, another one - ICanCreate + ICanRemove, etc.

Where to put the save/pre save methods in a domain object?

I want to enforce some rules every time a domain object is saved but i don't know the best way to achieve this. As, i see it, i have two options: add a save method to the domain object, or handle the rules before saving in the application layer. See code sample below:
using System;
namespace Test
{
public interface IEmployeeDAL
{
void Save(Employee employee);
Employee GetById(int id);
}
public class EmployeeDALStub : IEmployeeDAL
{
public void Save(Employee employee)
{
}
public Employee GetById(int id)
{
return new Employee();
}
}
public interface IPermissionChecker
{
bool IsAllowedToSave(string user);
}
public class PermissionCheckerStub : IPermissionChecker
{
public bool IsAllowedToSave(string user)
{
return false;
}
}
public class Employee
{
public virtual IEmployeeDAL EmployeeDAL { get; set; }
public virtual IPermissionChecker PermissionChecker { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public void Save()
{
if (PermissionChecker.IsAllowedToSave("the user")) // Should this be called within EmployeeDAL?
EmployeeDAL.Save(this);
else
throw new Exception("User not permitted to save.");
}
}
public class ApplicationLayerOption1
{
public virtual IEmployeeDAL EmployeeDAL { get; set; }
public virtual IPermissionChecker PermissionChecker { get; set; }
public ApplicationLayerOption1()
{
//set dependencies
EmployeeDAL = new EmployeeDALStub();
PermissionChecker = new PermissionCheckerStub();
}
public void UnitOfWork()
{
Employee employee = EmployeeDAL.GetById(1);
//set employee dependencies (it doesn't seem correct to set these in the DAL);
employee.EmployeeDAL = EmployeeDAL;
employee.PermissionChecker = PermissionChecker;
//do something with the employee object
//.....
employee.Save();
}
}
public class ApplicationLayerOption2
{
public virtual IEmployeeDAL EmployeeDAL { get; set; }
public virtual IPermissionChecker PermissionChecker { get; set; }
public ApplicationLayerOption2()
{
//set dependencies
EmployeeDAL = new EmployeeDALStub();
PermissionChecker = new PermissionCheckerStub();
}
public void UnitOfWork()
{
Employee employee = EmployeeDAL.GetById(1);
//do something with the employee object
//.....
SaveEmployee(employee);
}
public void SaveEmployee(Employee employee)
{
if (PermissionChecker.IsAllowedToSave("the user")) // Should this be called within EmployeeDAL?
EmployeeDAL.Save(employee);
else
throw new Exception("User not permitted to save.");
}
}
}
What do you do in this situation?
I would prefer the second approach where there's a clear separation between concerns. There's a class responsible for the DAL, there's another one responsible for validation and yet another one for orchestrating these.
In your first approach you inject the DAL and the validation into the business entity. Where I could argue if injecting a validator into the entity could be a good practice, injecting the DAL into the business entity is is definitely not a good practive IMHO (but I understand that this is only a demonstration and in a real project you would at least use a service locator for this).
If I had to choose, I'd choose the second option so that my entities were not associated to any DAL infrastructure and purely focused on the domain logic.
However, I don't really like either approach. I prefer taking more of an AOP approach to security & roles by adding attributes to my application service methods.
The other thing I'd change is moving away from the 'CRUD' mindset. You can provide much granular security options if you secure against specific commands/use cases. For example, I'd make it:
public class MyApplicationService
{
[RequiredCommand(EmployeeCommandNames.MakeEmployeeRedundant)]
public MakeEmployeeRedundant(MakeEmployeeRedundantCommand command)
{
using (IUnitOfWork unitOfWork = UnitOfWorkFactory.Create())
{
Employee employee = _employeeRepository.GetById(command.EmployeeId);
employee.MakeRedundant();
_employeeRepository.Save();
}
}
}
public void AssertUserHasCorrectPermission(string requiredCommandName)
{
if (!Thread.CurrentPrincipal.IsInRole(requiredCommandName))
throw new SecurityException(string.Format("User does not have {0} command in their role", requiredCommandName));
}
Where you'd intercept the call to the first method and invoke the second method passing the thing that they must have in their role.
Here's a link on how to use unity for intercepting: http://litemedia.info/aop-in-net-with-unity-interception-model
Where to put the save/pre save methods in a domain object?
Domain objects are persistent-ignorant in DDD. They are unaware of the fact that sometimes they get 'frozen' transported to some storage and then restored. They do not notice that. In other words, domain objects are always in a 'valid' and savable state.
Permission should also be persistent-ignorant and based on domain and Ubiquitous Language, for example:
Only users from Sales group can add OrderLines to an Order in a
Pending state
As opposed to:
Only users from Sales group can save Order.
The code can look like this:
internal class MyApplication {
private IUserContext _userContext;
private ICanCheckPermissions _permissionChecker;
public void AddOrderLine(Product p, int quantity, Money price, ...) {
if(!_permissionChecker.IsAllowedToAddOrderLines(_userContext.CurrentUser)) {
throw new InvalidOperationException(
"User X is not allowed to add order lines to an existing order");
}
// add order lines
}
}

Class Naming Conventions with Layered Architecture and Entity Framework

I'm designing a layered architecture (Service/Business Logic Layer, Data Access Layer) and am struggling with the intersection of a few problems.
Entity Framework 4.1 does not support interfaces directly
My Interfaces contain collections of other interfaces with read/write properties
This means using an implementing class won't work either, since it would still refers to another interface type
Example (please excuse the poorly written code, this is ad-hoc from my brain):
Data Access Layer
public interface IEmployer
{
string Name { get; set; }
ICollection<IEmployee> Employees { get; set; }
}
public interface IEmployee
{
string Name { get; set; }
}
public class Employer : IEmployer
{
public string Name { get; set; }
public ICollection<IEmployee> Employees { get; set; }
}
public class Employee : IEmployee
{
public string Name { get; set; }
}
public class DataManager
{
public IEmployer GetEmployer(string name) { ... }
public IEmployee CreateEmployeeObject(string name) { ... }
public void Save(IEmployer employer) { ... }
public void Save(IEmployee employee) { ... }
}
Service Layer
[DataContract]
public class Employee
{
[DataMember]
public string Name { get; set; }
}
public class HireService
{
public void HireNewEmployee(Employee newEmployee, string employerName)
{
DataManager dm = new DataManager();
IEmployer employer = dm.GetEmployer(employerName);
IEmployee employee = dm.CreateEmployeeObject(newEmployee.Name);
dm.Save(employee);
employer.Employees.Add(employee);
dm.Save(employer);
}
}
Without EF, the above works fine. The IEmployee type is used in the service layer, and does not conflict with the Employee data contract type. However, EF cannot use an interface, so I would be required to use class instead of an interface.
I see a few options:
Change IEmployer/IEmployee to classes, leaving the same names
Change IEmployer/IEmployee to classes, rename to EmployerDAL/EmployeeDAL
Change IEmployer/IEmployee to classes, rename to Employer/Employee, sprinkle using EmployerDL = DataLayer.Employer at the beginning of any service classes using it
What naming convention should I follow for class names which are defined in both the business and data layer?
Similar question to this: What's the naming convention for classes in the DataAccess Project? except that EF causes a problem with interfaces.
Actually the class defined in your DAL should be the one used in your business layer - those are your real domain objects. Classes exposed from your business layer are just data transfer objects so if you want to build any convention you should imho rename your data contracts.
Anyway the naming convention is something really subjective. Choose the way which best fits your needs and be consistent in that naming.

Bundling a list of entities into a component

With FluentNHibernate I have mapped a UserPreference entity which references the GeneralPreference, GeneralPreferenceOption, and Profile entities:
public class UserPreference
{
public virtual long Id { get; set; }
public virtual Profile Profile { get; set; }
public virtual GeneralPreference Preference { get; set; }
public virtual GeneralPreferenceOption Value { get; set; }
}
It's easy enough to map a list of UserPreference on my Profile entity, but what I actually would like to do is wrap this list inside another class so that I can simplify operations concerning a user's given preferences:
public class Preferences
{
public IList<UserPreferences> UserPreferences{get;set;}
public Language Language {
{
//look up the language preference here
}
}
This kind of feels like a Component, but Components were not created for this type of scenario. Does anyone have any pointers on how I might map this?
I figured out a way to do this by mapping a private property on my Profile Entity. Using the techniques from the Fluent NHibernate wiki on mapping private properties (http://wiki.fluentnhibernate.org/Fluent_mapping_private_properties) I map a collection of UserPreference on my Profile Entity. Then I create another class PropertyHandler which takes an IEnumerable as a constructor parameter and make an instance of this a public property on Profile as well:
public class Profile
{
private PreferenceHandler _preferenceHandler;
get { return _preferenceHandler ?? (_preferenceHandler = new PreferenceHandler(UserPreferences)); }
private IEnumerable<UserPreference> UserPreferences { get; set; }
public static class Expressions
{
public static readonly Expression<Func<Profile, IEnumerable<UserPreference>>> UserPreferences = x => x.UserPreferences;
}
}
Notice the nested static class. It's used to enable mapping of a private property with FluentNHibernate.
The mapping class looks something like this:
public class ProfileMappings : ClassMap<Profile>
{
public ProfileMappings()
{
//... other mappings
HasMany(Profile.Expressions.UserPreferences);
}
}
I can now use the PreferenceHandler class to create helper methods over my collection of UserPreference.
An alternative is to build extension methods for IEnumberable. This works, but I decided not to do this because
1) I'm not really extending the IEnumerable functionality and
2) my helper methods disappear inamongst all the other IEnumerable extension methods making the whole thing a bit cluttered.