I am designing the different layers of a scheduler in c#. This is going to be a service running in the background without a GUI.
This is my baseline for the architecture (ofcourse only being a small snippet of the structure.
I am uncertain about "best-practice" in terms of archeticture. I have been reading about, POCOs, Value Objects, DTOs, Domain Model and from what I can understand, the presented below is a wrong approach to DTOs.
In my class "ScheduleDTP", I have several methods doing some relativ complex manipulations with date coming from the database. CalculatePriority is a simplified example of one of the methods
Database properties:
ID, Name, Frequency, LastRun
Manipulated properties:
Priority
The purpose of the jobmanager is to evaluate all schedules and on-demands.
To my understanding the DTO should only contain the data, and transfer that between the different layers. I also believe that this should not be the JobManagers resposibility either.
public class ScheduleDTO
{
public Guid ID { get; set; }
public string Name { get; set; }
public int Frequency { get; set; }
public DateTime LastRun { get; set; }
//Calculation based on the values above
public double Priority
{
get
{
return CalculatePriority();
}
}
public double CalculatePriority()
{
return (DateTime.Now - LastRun.AddSeconds(Frequency)).TotalSeconds / 100;
}
}
Should I create some different type of object, POCO, Domail Model, ..., that manipulates the data in the DTOs?
I really appreciate any help about how to construct the different layers or something that that could lead me in the right direction
This is normally handled by a Service layer (aka business logic layer, BLL, etc). The service layer's job is to hold the core business logic. There exists a long-standing argument about whether this layer should be used, or if it should be integrated into the domain objects. See this post for more details and do some googling about anemic domain models and transaction scripts.
In general, when I see anything called "Manager", I immediately flag it for close inspection. It is likely violating rules around Single Responsibility Principal. It ends up creating "God Objects" which are usually a very dangerous anti-pattern.
Related
I hear that for a small project DTO's are not recommended for example here and here. I wonder if it is OK for a considerably small project (team-wise) to merge non-persistent properties in the domain models? eg:
namespace Domain.Entities
{
public class Candidate : BaseEntity
{
public Candidate()
{
// some construction codes
}
// region persistent properties
public string FirstName { get; set; }
public string LastName { get; set; }
public bool? IsMale { get; set; }
public DateTime BirthDate { get; set; }
// other properties ...
// region non-persistent properties
public string FullName => $"{FirstName} {LastName}";
}
}
Is this just keeping simple or am loosing anything valuable this way?
I'm not advocating a particular approach, just sharing information...
I wouldn't put your computation of FullName in a DTO. A DTO is just a simple object, really more of a struct, and shouldn't have any logic in it. The purpose of a DTO is to move data from one layer/tier to another and create a layer of indirection that allows your domain model to evolve independent of your clients. FullName on your Entity as a non-persistent property makes more sense here than in the DTO. If you want to go full enterprise, it would be in a transformer/adapter.
If your project is really small, and is likely never going to grow, then abandoning the DTO can be acceptable. Just keep in mind, that if your project grows you may have to do some refactoring, and there are some other things to consider...
Another benefit of the DTO is keeping some data where it needs to stay. For example, if you have sensitive data in your entity object and you don't put something in place to prevent it from being returned in a web request, you just leaked some information off your app server layer (think the password field in your user entity). A DTO requires you to think about what is being sent to/from the client and makes including data an explicitly intentional act vs an unintentional act. DTOs also make it easier to document what is really required for a client request.
That being said, each DTO is now code you have to write and maintain, which is the main reason to avoid them, and a model change can have a noticeable ripple effect through the system.
It comes down to deciding how you want to handle potential data leakage, how you want to manage your clients (if you can), and how complex your model may get.
So, I've got an aggregate( Project ) that has a collection of entities (ProjectVariables) in it. The variables do not have Ids on them because they have no identity outside of the Project Aggregate Root.
public class Project
{
public Guid Id { get; set; }
public string Name { get; set; }
public List<ProjectVariable> ProjectVariables { get; set; }
}
public class ProjectVariable
{
public string Key { get; set; }
public string Value { get; set; }
public List<string> Scopes { get; set; }
}
The user interface for the project is an Angular web app. A user visits the details for the project, and can add/remove/edit the project variables. He can change the name. No changes persist to the database until the user clicks save and the web app posts some json to the backend, which in turns passes it down to the domain.
In accordance to DDD, it's proper practice to have small, succinct methods on the Aggregate roots that make atomic changes to them. Examples in this domain could be a method Project.AddProjectVariable(projectVariable).
In order to keep this practice, that means that the front end app needs to track changes and submit them something like this:
public class SaveProjectCommand
{
public string NewName { get; set; }
public List<ProjectVariable> AddedProjectVariables { get; set; }
public List<ProjectVariable> RemovedProjectVariables { get; set; }
public List<ProjectVariable> EditedProjectVariables { get; set; }
}
I suppose it's also possible to post the now edited Project, retrieve the original Project from the repo, and diff them, but that seems a little ridiculous.
This object would get translated into Service Layer methods, which would call methods on the Aggregate root to accomplish the intended behaviors.
So, here's where my questions come...
ProjectVariables have no Id. They are transient objects. If I need to remove them, as passed in from the UI tracking changes, how do identify the ones that need to be removed on the Aggregate? Again, they have no identification. I could add surrogate Ids to the ProjectVariables entity, but that seems wrong and dirty.
Does change tracking in my UI seem like it's making the UI do too much?
Are there alternatives mechanisms? One thought was to just replace all of the ProjectVariables in the Project Aggregate Root every time it's saved. Wouldn't that have me adding a Project.ClearVariables() and the using Project.AddProjectVariable() to the replace them? Project.ReplaceProjectVariables(List) seems to be very "CRUDish"
Am I missing something a key component? It seems to me that DDD atomic methods don't mesh well with a pattern where you can make a number of different changes to an entity before committing it.
In accordance to DDD, it's proper practice to have small, succinct
methods on the Aggregate roots that make atomic changes to them.
I wouldn't phrase it that way. The methods should, as much as possible, reflect cohesive operations that have a domain meaning and correspond with a verb or noun in the ubiquitous language. But the state transitions that happen as a consequence are not necessarily small, they can change vast swaths of Aggregate data.
I agree that it is not always feasible though. Sometimes, you'll just want to change some entities field by field. If it happens too much, maybe it's time to consider changing from a rich domain model approach to a CRUD one.
ProjectVariables have no Id. They are transient objects.
So they are probably Value Objects instead of Entities.
You usually don't modify Value Objects but replace them (especially if they're immutable). Project.ReplaceProjectVariables(List) or some equivalent is probably your best option here. I don't see it as being too CRUDish. Pure CRUD here would mean that you only have a setter on the Variables property and not even allowed to create a method and name it as you want.
I'm a novice trying to wrap my head around MVVM. I'm trying to build something and have not found an answer on how to deal with this:
I have several models/entities, some of which have logical connections and I am wondering where/when to bring it all together nicely.
Assume we have a PersonModel:
public class PersonModel
{
public int Id { get; set; }
public string Name { get; set; }
...
}
And a ClubModel:
public class ClubModel
{
public int Id { get; set; }
public string Name { get; set; }
...
}
And we have MembershipModel (a Person can have several Club memberships):
public class MembershipModel
{
public int Id { get; set; }
public PersonId { get; set; }
public ClubId { get; set; }
}
All these models are stored somewhere, and the models are persisted "as in" in that data storage.
Assume we have separate repositories in place for each of these models that supplies the standard CRUD operations.
Now I want to create a view model to manage all Persons, e.g. renaming, adding memberships, etc. -> PersonMangementViewModel.
In order to nicely bind a Person with all its properties and memberships, I would also create a PersonView(?)Model that can be used in the PersonManagementViewModel. It could contain e.g. view relevant properties and also the memberships:
public class PersonViewModel : PersonModel
{
public Color BkgnColor { get return SomeLogic(); }
public IEnumerable<MembershipModel> { get; set; }
...
}
My question here is, how would I smartly go about getting the Membership info into the PersionViewModel? I could of course create an instance of the MemberShipRepo directly in the PersionViewModel but that seems not nice, especially if you have a lot of Persons. I could also create all repositories in the PersonManagementViewModel and then pass references into the PersonViewModel.
Or does it make more sense to create another layer (e.g. "service" layer) that returns primarily the PersonViewModel, therefore uses the individual repositories and is called from the PersonManagementViewModel (thus removing the burden from it and allowing for re-use of the service elsewhere)?
Happy to have pointed out conceptional mistakes or some further reading.
Thanks
You are creating separate model for each table I guess. Does not matter, but your models are fragmented. You can consider putting related data together using Aggregate Root and Repository per Aggregate root instead of per model. This concept is discussed under DDD. But as you said you are new to MVVM, there is already lot much to learn. Involving DDD at this stage will only complicate the things.
If you decide to keep the things as is, best and quick thing I can guess is what you are doing now. Get instance of model from data store in View Model (or whatever your location) and map somehow. Tools like Automapper are good but they does not fit each situation. Do not hesitate to map by hand if needed. You can also use mix approach (Automapper + map by hand) to simplify the things.
About service layer, sure... why not. Totally depends on you. If used, this layer typically contain your business logic, mapping, formatting of data, validations etc. Again, each of that thing is up to you.
My suggestions:
Focus on your business objectives first.
Design patterns are good and helpful. Those are extract of many exceptionally capable developers to solve specific problem. Do use them. But, do not unnecessarily stick to it. Read above suggestion. In short, avoid over-engineering. Design patterns are created to solve specific problem. If you do not have that problem, then do not mess-up your code with unnecessary pattern.
Read about Aggregate Root, DDD, Repository etc.
Try your best to avoid Generic Repository.
I've been entering the advanced stage of C# recently and I've seen a lot of applications that implement losely coupling and dependency injection. I've seen the word "Service" a lot associated with classes, I suppose you would call them Service classes? I've also seen classes in this project which include the word Repository, say you has a called 'Player', there would be 2 more classes 'PlayerService' and 'PlayerRepository' classes.
I've checked Linda, TreeHouse, Udemy and many other sites. I've even google the subject but it seems to bring up hundreds of results all leading to different things. None of these links really answer my question in simple plain detail, atleast none that I can understand.
Can anyone help explain this? Why do I need them, when should I use them, what are they?
Well, hard to make a specific explanation without seeing the code but in general terms the concept of a Repository refers to data layer components and the term service - mostly in ASP.NET world refers to business layer components.
You separate these layers from each other so they can be maintained, tested, expanded in isolation. Ideal architectures expose the functionality of these layers via Interfaces - especially the Repository layer. On the Service layer you can take these dependencies through constructor as Interfaces. Using an IoC container and Dependency Injection patterns, you can then register concrete classes to these interfaces and build your objects in a central location aka. Object Composition Root. that allows you easily manage your dependencies in a central location, rather then each dependency instantiated, passed around in scattered places within your code.
This answer is just a pointer to give you an overview. These are topics you should delve deeper by self research and digest.
The Repository pattern is used to abstract away how a class is persisted. This allows you to change the underlying Database or ORM mapper without influencing the persisted classes. See Using Repository Pattern for Abstracting Data Access from a Cache and Data Store.
A service is used if multiple classes are taking part in a certain usecase and none of these classes should have the responsibility to coordinate the other classes. (Maybe these classes do not even hold direct references to each other.) In this case, put the code that handles the interplay between the classes into a service method and pass the affected objects to it.
Note that if the affected classes are in a direct parent-child relationship, you could let the parent coordinate its children directly, without introducing a service. But this might lead to code that is hard to understand.
Let me give an example: assume we want to commit Transactions. After a Transaction was commited, we want to update the Person who has the transaction with the (denormalized) timestamp of the most recent transaction. As you can see, Person does not hold a direct reference to the transaction.
public class Person {
public long Id { get; set; }
public string Name { get; set; }
public DateTime? LastTransactionTimestamp { get; set; }
}
public class Transaction {
public long Id { get; set; }
public long PersonId { get; set; }
public DateTime Timestamp { get; set; }
public void Commit() {
Timestamp = DateTime.Now;
}
}
Now we have the problem where we should put the logic. If we put it into the Person class, it would need Repository access to load the Transaction (because it holds no direct reference). But it should only be concerned with storing its own data, not loading unrelated data from the DB. If we put it into the Transaction class, it does not know if it was the latest Transaction for this Person (because it does not see the other transactions).
So the solution is to put the logic into a service. If the service needs DB access, we inject a repository into it.
public class PersonTransactionService {
private readonly IDbSet<Transaction> _allTransactions;
public PersonTransactionService(IDbSet<Transaction> allTransactions) {
_allTransactions = allTransactions;
}
public void Commit(Person person, Transaction transaction) {
transaction.Commit();
var mostRecent = _allTransactions
.Where(t => t.PersonId == person.Id)
.OrderBy(t => t.Timestamp)
.LastOrDefault();
if (mostRecent != null) {
person.LastTransactionTimestamp = mostRecent.Timestamp;
}
}
}
Let's say that I want to create a blog application with these two simple persistence classes used with EF Code First or NHibernate and returned from repository layer:
public class PostPersistence
{
public int Id { get; set; }
public string Text { get; set; }
public IList<LikePersistence> Likes { get; set; }
}
public class LikePersistence
{
public int Id { get; set; }
//... some other properties
}
I can't figure out a clean way to map my persistence models to domain models. I'd like my Post domain model interface to look something like this:
public interface IPost
{
int Id { get; }
string Text { get; set; }
public IEnumerable<ILike> Likes { get; }
void Like();
}
Now how would an implementation underneath look like? Maybe something like this:
public class Post : IPost
{
private readonly PostPersistence _postPersistence;
private readonly INotificationService _notificationService;
public int Id
{
get { return _postPersistence.Id }
}
public string Text
{
get { return _postPersistence.Text; }
set { _postPersistence.Text = value; }
}
public IEnumerable<ILike> Likes
{
//this seems really out of place
return _postPersistence.Likes.Select(likePersistence => new Like(likePersistence ));
}
public Post(PostPersistence postPersistence, INotificationService notificationService)
{
_postPersistence = postPersistence;
_notificationService = notificationService;
}
public void Like()
{
_postPersistence.Likes.Add(new LikePersistence());
_notificationService.NotifyPostLiked(Id);
}
}
I've spent some time reading about DDD but most examples were theoretical or used same ORM classes in domain layer. My solution seems to be really ugly, because in fact domain models are just wrappers around ORM classes and it doens't seem to be a domain-centric approach. Also the way IEnumerable<ILike> Likes is implemented bothers me because it won't benefit from LINQ to SQL. What are other (concrete!) options to create domain objects with a more transparent persistence implementation?
One of the goals of persistence in DDD is persistence ignorance which is what you seem to be striving for to some extent. One of the issues that I see with your code samples is that you have your entities implementing interfaces and referencing repositories and services. In DDD, entities should not implement interfaces which are just abstractions of itself and have instance dependencies on repositories or services. If a specific behavior on an entity requires a service, pass that service directly into the corresponding method. Otherwise, all interactions with services and repositories should be done outside of the entity; typically in an application service. The application service orchestrates between repositories and services in order to invoke behaviors on domain entities. As a result, entities don't need to references services or repositories directly - all they have is some state and behavior which modifies that state and maintains its integrity. The job of the ORM then is to map this state to table(s) in a relational database. ORMs such as NHibernate allow you to attain a relatively large degree of persistence ignorance.
UPDATES
Still I don't want to expose method with an INotificationService as a
parameter, because this service should be internal, layer above don't
need to know about it.
In your current implementation of the Post class the INotificationService has the same or greater visibility as the class. If the INotificationService is implemented in an infrastructure layer, it already has to have sufficient visibility. Take a look at hexagonal architecture for an overview of layering in modern architectures.
As a side note, functionality associated with notifications can often be placed into handlers for domain events. This is a powerful technique for attaining a great degree of decoupling.
And with separate DTO and domain classes how would you solve
persistence synchronization problem when domain object doesn't know
about its underlying DTO? How to track changes?
A DTO and corresponding domain classes exist for very different reasons. The purpose of the DTO is to carry data across system boundaries. DTOs are not in a one-one correspondence with domain objects - they can represent part of the domain object or a change to the domain object. One way to track changes would be to have a DTO be explicit about the changes it contains. For example, suppose you have a UI screen that allows editing of a Post. That screen can capture all the changes made and send those changes in a command (DTO) to a service. The service would load up the appropriate Post entity and apply the changes specified by the command.
I think you need to do a bit more research, see all the options and decide if it is really worth the hassle to go for a full DDD implementation, i ve been there myself the last few days so i ll tell you my experience.
EF Code first is quite promising but there are quite a few issues with it, i have an entry here for this
Entity Framework and Domain Driven Design. With EF your domain models can be persisted by EF without you having to create a separate "persistence" class. You can use POCO (plain old objects) and get a simple application up and running but as i said to me it s not fully mature yet.
If you use LINQ to SQL then the most common approach would be to manually map a "data transfer object" to a business object. Doing it manually can be tough for a big application so check for a tool like Automapper. Alternatively you can simply wrap the DTO in a business object like
public class Post
{
PostPersistence Post { get; set;}
public IList<LikePersistence> Likes { get; set; }
.....
}
NHibernate: Not sure, havent used it for a long time.
My feeling for this (and this is just an opinion, i may be wrong) is that you ll always have to make compromises and you ll not find a perfect solution out there. If you give EF a couple more years it may get there. I think an approach that maps DTOs to DDD objects is probably the most flexible so looking for an automapping tool may be worth your time. If you want to keep it simple, my favourite would be some simple wrappers around DTOs when required.