At work I've got thrown into developing a legacy enterprice application, that still is under production and stalled for the last few months because of bad design and instability.
So we've started using EF5 and applying some design patterns / layers to our application.
What I'm struggling to understand is: what exactly should the Service Layer do in our case? Would it be over-architecturing or would it provide some benefits without adding unneccesary comlexity?
Let's show you what we've got so far:
we've introduced EF (Code First with POCOs) to map our legacy database (works reasonably well)
we've created repositories for the most stuff we need in our new Data Layer (specific implementations, I don't see any kind of benefit regarding seperation of concern using generic repos..)
Now in the specific case it is about calculating prices for an article - either by getting a price from an arcile directly or from the group the article is in (if there is no price specified). It's getting a lot more complex, because there also are different pricelists involved (depending on the complete value of the order) and depending on the customer who also can have special prices etc.
So my main question is: who is responsible for getting the correct price?
My thoughts are:
The order has to know of the items it consists of. Those items on the other hand have to know what their price is, but the order must not know of how to calculate the item's price, just that it has to summarize their costs.
Excert of my code at the moment:
ArticlePrice (POCO, Mappings soon to be swapped by Fluid API)
[Table("artikeldaten_preise")]
public class ArticlePrice : BaseEntity
{
[Key]
[Column("id")]
public int Id { get; set; }
[Column("einheit")]
public int UnitId { get; set; }
[ForeignKey("UnitId")]
public virtual Unit Unit { get; set; }
[Column("preisliste")]
public int PricelistId { get; set; }
[ForeignKey("PricelistId")]
public virtual Pricelist Pricelist { get; set; }
[Column("artikel")]
public int ArticleId { get; set; }
[ForeignKey("ArticleId")]
public virtual Article Article { get; set; }
public PriceInfo PriceInfo { get; set; }
}
Article Price Repository:
public class ArticlePriceRepository : CarpetFiveRepository
{
public ArticlePriceRepository(CarpetFiveContext context) : base(context) {}
public IEnumerable<ArticlePrice> FindByCriteria(ArticlePriceCriteria criteria)
{
var prices = from price in DbContext.ArticlePrices
where
price.PricelistId == criteria.Pricelist.Id
&& price.ArticleId == criteria.Article.Id
&& price.UnitId == criteria.Unit.Id
&& price.Deleted == false
select price;
return prices.ToList();
}
}
public class ArticlePriceCriteria
{
public Pricelist Pricelist { get; set; }
public Article Article { get; set; }
public Unit Unit { get; set; }
public ArticlePriceCriteria(Pricelist pricelist, Article article, Unit unit)
{
Pricelist = pricelist;
Article = article;
Unit = unit;
}
}
PriceService (does have a horriffic code smell...)
public class PriceService
{
private PricelistRepository _pricelistRepository;
private ArticlePriceRepository _articlePriceRepository;
private PriceGroupRepository _priceGroupRepository;
public PriceService(PricelistRepository pricelistRepository, ArticlePriceRepository articlePriceRepository, PriceGroupRepository priceGroupRepository)
{
_pricelistRepository = pricelistRepository;
_articlePriceRepository = articlePriceRepository;
_priceGroupRepository = priceGroupRepository;
}
public double GetByArticle(Article article, Unit unit, double amount = 1, double orderValue = 0, DateTime dateTime = new DateTime())
{
var pricelists = _pricelistRepository.FindByDate(dateTime, orderValue);
var articlePrices = new List<ArticlePrice>();
foreach (var list in pricelists)
articlePrices.AddRange(_articlePriceRepository.FindByCriteria(new ArticlePriceCriteria(list, article, unit)));
double price = 0;
double priceDiff = 0;
foreach (var articlePrice in articlePrices)
{
switch (articlePrice.PriceInfo.Type)
{
case PriceTypes.Absolute:
price = articlePrice.PriceInfo.Price;
break;
case PriceTypes.Difference:
priceDiff = priceDiff + articlePrice.PriceInfo.Price;
break;
}
}
return (price + priceDiff) * amount;
}
public double GetByPriceGroup(PriceGroup priceGroup, Unit unit)
{
throw new NotImplementedException("not implemented yet");
}
//etc. you'll get the point that this approach might be completely WRONG
}
My final questions are:
How do I correctly model my problem? Is it correct, that I am on my way of overarchitecturing my code?
How would my Service Layer correctly look like? Would I rather have a ArticlePriceService, an ArticleGroupPriceService, etc.? But who would connect that pieces and calculate the correct price? Would that e.g. be the responsibility of an OrderItemService that has a method "GetPrice"? But then again the orderItemService would have to know about the other services..
Please try to provide me with possible solutions regarding architecture, and which object/layer does what.
Feel free to ask me additional questions if you need more info!
You did present a simple scenario which the Repository itself might be sufficient.
Do you have more repositories?
Do you expect you application to grow, and have more repositories in use?
Having a service layer that abstract the data layer is recommended and in use by most of the applications/examples that I have seen, and the overhead is not that significant.
One reason for using services might pop-up when you would like to fetch data from several different repositories, and then perform some kind of aggregation / manipulations on the data.
A Service layer would then provide the manipulation logic, while the service consumer would not have to deal with several different repositories.
You should also think of situations where you might want to have more then one entity changed in one transaction (Meaning - more than one repository), and saving the changes to the DB only when all update actions where successful.
That situation should imply using the Unit Of Work Pattern, and probably will conclude the use of a Service Layer, to enable proper unit-testing.
When i started with objects and architecture, my main problem was to give a good name to classes.
To me, it seems your service should be called "ShopService" (or something equivalent). Then your method GetByArticle, should be nammed GetPriceByArticle.
The idea of changing the name of the service for something bigger than just the price would be more meaningfull and would also address other issues (like your OrderPriceService you wonder about).
Maybe you can ask yourself "What is the name of my page or window that interracts with this service ?" Is there only one or more ? If more, what do they have in common ?
This could help you figure out a good name for your service, and consequently different methods to acquire what each needs.
Tell me more. I will be please to help.
Related
I've been reading about DDD and am still confused about aggregate root.
Imagine that I have a situation similar to a blog, where people can create posts and add comments to other posts.
Rules:
-Everybody needs to have an account to add post or comment
-Users are able to delete their own comments only
With that in mind, I would need the following objects:
-Post
-PostComment
-User
So, I created only the Post object as aggregate root and added some business logic to it
public class User : EntityBase
{
public string Name { get; set; }
public string Avatar { get; set; }
}
public class Post : EntityBase, IAggregate
{
public string Title { get; set; }
public string Content { get; set; }
public User Creator { get; set; }
private IList<PostComment> Comments { get; set; }
public void AddComment(PostComment comment)
{
this.Comments.Add(comment);
}
public void DeleteComment(PostComment comment, int userId)
{
if (comment.Creator.Id != userId)
throw new Exception("You cannot delete a comment that is not yours. blablabla");
this.Comments.Add(comment);
}
public IList<PostComment> GetComments()
{
return this.Comments;
}
}
public class PostComment : EntityBase
{
public string Comment { get; set; }
public User Creator { get; set; }
}
Am I doing this correctly? I mean, is the business logic in the right place? Or I should've made PostComment as aggregate root too and added the logic of add/delete in it?
Warning: it's difficult to reason about DDD using toy problems. Especially in your core domain, the point of all of this work is that you can customize things to meet your local needs. If you didn't need a bespoke solution, you'd just buy some off-the-shelf solution, integrate and get on with it.
Or I should've made PostComment as aggregate root too and added the logic of add/delete in it?
Maybe. Aggregates are best thought of as atoms, you load the entire aggregate, make your changes, save the results.
So if you find yourself with many concurrent attempts to modify the same aggregate, then you have to deal with a bunch of contention issues. Alice can't change her comment while Bob is changing his; we have to do them one at a time (to avoid losing changes).
On the other hand, if each comment is an aggregate of its own, then Bob and Alice can make their changes in parallel, without needing to rerun the "business logic" because the other person's change happened first.
Which is great, when it is free. But it isn't free -- the cost you pay is that the information is now distributed, and you have to deal with the fact that the changes have different timing. You'll sometimes see "eventual consistency" used here -- because the authoritative information is distributed, there will be times where not all of the observers have the same sets of changes.
In most domains, this is fine: race conditions don't exist. But trying to perform an all or nothing change across distributed data is a nightmare.
On the other hand, if you are willing to accept that changes happen at different times, then separating the aggregates out is fine.
Example: Twitter. Bob tweets something dumb. Alice tweets that Bob is dumb, with a link to his tweet. Bob deletes his tweet. And that's all fine, because we're comfortable with the fact that Alice's tweet has a link to something that is no longer available.
It is often the case that information that comes from the outside world can be its own aggregate, because what we are really doing at that stage is caching data, which is already stale by the time we receive it.
You may also want to review Mauro Servienti's talk All Our Aggregates Are Wrong, which discusses the heuristics for breaking down an aggregate into smaller pieces.
Am I doing this correctly? I mean, is the business logic in the right place? Or I should've made PostComment as aggregate root too and added the logic of add/delete in it?
Partially! I consider the logic is in the right place and PostComment should not be an aggregate root. But if you wants to take off more about DDD I consider that there are some another points to review before continue. I hope I can help you some way in the explanations bellow.
I have reviewed the code and refactored it to explain some points you can reconsider. Try to read it, compare and understand before read my explanation below.
// you can simplify your DomainModel removing the IAggregate plus adding generics
public abstract class Entity<T>
{
public T Id { get; set; }
}
// this is an Aggregate Root
public class Person : Entity<int>
{
public string Name { get; set; }
public string Avatar { get; set; }
public override string ToString()
{
return Name;
}
}
//this is an Aggregate Root
public class Post : Entity<int>
{
private List<Comment> _comments = new List<Comment>();
public string Title { get; set; }
public string Content { get; set; }
public Person Author { get; set; }
public IReadOnlyList<Comment> Comments => _comments;
public void Reply(Comment comment)
{
_comments.Add(comment);
}
public void Delete(Comment comment, int personId)
{
if (!AreSame(comment.Author, personId))
throw new Exception("You cannot delete a comment that is not yours. blablabla");
_comments.Add(comment);
}
private bool AreSame(Person author, int personId)
{
return author.Id == personId;
}
public override string ToString()
{
return Title;
}
}
// this is a Value Object part of Post Aggregate
public struct Comment
{
public DateTime Date;
public string Text;
public Person Author;
public Comment(DateTime date, string text, Person author)
{
Date = date;
Text = text;
Author = author;
}
public override string ToString()
{
return $"{Date} - {Author}: {Text}";
}
}
If the PostComment is part of Post Aggregate, it can't be an EntityBase, because each Aggragate should have only one root (Id). You're modeling a domain where a Post may have N Comments. You can consider the PostComment as a Value Object instead an Entity removing his Id.
You should pay attention about the names you are using. Try to sound more natural. It is called, ubiquitous language, the words everybody speak.
User is a description that just have a sense in system's context, in other words, you should have a User if you dealing with Security or Authentication contexts, in a Blog Context you have a Person acting as Author.
Increase readability using terms your users says. Reply may be more natural than AddComment.
public void Reply(Comment comment)
{
_comments.Add(comment);
}
Increase readability adding names for your conditions:
public void Delete(Comment comment, int personId)
{
if (!AreSame(comment.Author, personId))
throw new Exception("You cannot delete a comment that is not yours. blablabla");
_comments.Add(comment);
}
private bool AreSame(Person author, int personId)
{
return author.Id == personId;
}
So, I am writing a program, and getting my data using EF 6.
Basically, I though the simplest approach would be to have one class like this:
public class DataRetriever
{
public List<TEntity> GetAll<TEntity>() where TEntity : class
{
using (var Db = new Entity())
{
return Db.Set<TEntity>().ToList();
}
}
}
So then, you care start creating other classes on the basis of specifying which data you want to be collected. So say I have a list of carnival rides and one method is to get a single ride or something. SO then I would have the following:
public class SelectedRide
{
int RideId { get; set; }
string RideName { get; set; }
string DomValue { get; set; }
public SelectedRide(DataRetriever Retriever)
{
var Records = Retriever.GetAll<vwRideList>();
var Record = from x in Records
where x.RideId == RideId
select x;
RideName = Record.Single().RideName;
DomValue = Record.Single().DomValue;
}
}
Ride ID being an identity.
So then one could say that if another class like say we had multiple parks where rides were, could be public class SelectedPark it would have the same logic, but in the Retriever.GetAll<vwParkList>(); The ride list is now the park list. And so on.
I can't tell if this is quickly going to get out of hand if I say had 50 separate types of retrieving that needed to be done. Granted, I won't as I know the total scope of this program, but WHAT IF.
I've seen stuff like the repo pattern as well, but I can't tell if that's somewhat of a waste of time or not. I can't tell what I am getting out of it. This seemed to keep it generic enough that I am not writing the context in a million different places.
We just received a phase 1 release from a vendor to translate an archaic PowerBuilder application into C# MVC with Angular 5 (we have an Angular guy that has already mostly rewritten the front end in 7 so the security concerns from 5 are a nonissue). Since the statement of work only required them to reproduce the application there are next to zero validations on input because there wasn't much, if any, on the original application.
I have recently done some research into FluentValidation and like it for its reusability later in applications that will use the same overall data. However, looking at this code the models in the MVC are not normalized like they probably should be and so we have dozens of models that likely could be normalized out so that there would be less overlap in data fields such as First Name, Last Name, Address, Business Address etc.
I have basic experience with generics and reflection and have supported a few more advanced examples in the past. So I was trying to find some way to utilze these two concepts to make the validators more dynamic.
I was unable to find much in the way of more advanced FluentValidation examples other than the basic hard connection to a given named model. I have tried to use the generic T in place of the model but was unable to bridge the gap and access the object being passed into the validation.
public class FormValidator : AbstractValidator<ModelExample>
{
public FormValidation()
{
}
}
//tried to do something like this but wasn't able to access the .HasProperties. Although I was able to access the GetProperties,
//having trouble implementing it into the RuleFor however.
public class FormValidation<T> : AbstractValidator<T>
{
RuleFor(x => x.GetType().GetProperty(nameof({something if it exists}).{check stuff is valid}
{
public class ModelExample
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class OtherModelExample
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
My end goal would be to be able to pass related objects into a given validator and it would be able to determine if the properties existed and act accordingly.
This may be an issue where I don't really know how to ask the question in Google, I tend to have issue wording things in a way where it brings up what I would expect.
This also may not even be possible but if it could save me from writing a series of hard coupled validators that I might have to rewrite later if we ever are allowed to normalize the data flow it would be of great help.
Any articles or documentation with more advanced examples than the simple ones I find would be of great use even beyond this project. Most of the tutorials I find are very basic examples and I sometimes have a hard time picturing them in "real" code application.
Thanks
Instead of creating generic validators for a whole model, have you considered the reverse and creating them for each property?
If you use custom property validators you can specify the validator logic once, and then simply create a validator class per view model.
eg:
class Program
{
static void Main(string[] args)
{
var person = new Person
{
Name = "Ada",
NickName = "A"
};
var validator = new PersonValidator();
var result = validator.Validate(person);
//Should be a problem with the NickName
}
}
class Person
{
public string Name { get; set; }
public string NickName { get; set; }
}
class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleFor(x => x.Name).SetValidator(new NameValidator());
RuleFor(x => x.NickName).SetValidator(new NameValidator());
}
}
public class NameValidator : AbstractValidator<string>
{
public NameValidator()
{
RuleFor(x => x).Must(x => x.Length > 1)
.WithMessage("The name is not long enough");
}
}
This is probably a safer option too, as it's opt in rather than implicit.
I am trying to understand and implement different UI patterns in .NET to see the pros and cons and where they suite best.
I understand the main concept but I was creating an app and a question appeared.
Say we have a class Customer, which represents the core Information of a customer.
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string PostalCode { get; set; }
public string PhoneNumber { get; set; }
}
Now, if I create a WebView or WebForm to show all customers I can use this class to set as source f.e. to a DGV, being able to show all properties above.
But then I want to show for example a View/Form with the Revenue history of each customer.
So there is a class CustomerRevenue like
public class CustomerRevenue
{
public Revenue ActualYearExpectedRevenue { get; set; }
public IList<Revenue> RevenuePerYearList { get; set; }
public decimal ActualYearProjectedRevenue => CalculateYearProyection();
public decimal CalculateYearProyection(int year)
{
var daysInYear = DateTime.IsLeapYear(year) ? 365 : 366;
var actualYearRevenue = RevenuePerYearList.SingleOrDefault(x => x.Year == year);
var dayNumber = DateTime.Now.DayOfYear;
var projection = ((actualYearRevenue.Amount * daysInYear) / dayNumber);
return projection;
}
}
Here, to set RevenuePerYearList we need some time, since let's say we sell a lot and have a huge list of sells with huge lists of articles, so the calculation needs some time.
So now my question:
Should I then have "concrete" classes for each view/model with the data I want to show, i.e. here I would have apart of Customer class, say a CustomerRevenueModel
public class CustomerRevenueModel
{
private readonly CustomerRevenue _customerRevenue = new CustomerRevenue();
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string PostalCode { get; set; }
public CustomerRevenue CustomerRevenue
{
get { return _customerRevenue; }
}
}
}
which has (maybe) different properties, so I need to load this "heavy" properties when needed
or
should I stay with only one class (I mean, a customer always has a revenue) and leave the properties "empty"?
The first option makes me have a lot of classes, one for each view/form I want to show data for (maybe being able to reuse some models in various views/forms) but keeps all clean and in a valid state. And also each class can have it's own logic (domain logic - DDD)
The second option is less classes, less code, but some way I end having a huge (God) class, with all the properties a Customer has and all it's logic (methods). I load only the ones I need, but this appears really bad to me.
The third option is to have the big class with all properties and methods as my (domain)model, and create a "ViewModel" (which contains no methods, only props) each time I need to show sth. like above , using it as source for my GridView. This is the solution with more classes and code (big class + ViewModels + (maybe) DTOs), but also the more organized and SOLID design to my eyes... Here the use of a Mapper like AutoMapper would really help, mapping between objects
But this is the part I'm confused about...
Are these "ViewModels" a bad pattern using MVC or MVP?
Are this the same as the VM in MVVM? Which I Think not, since I've understood VM in MVVM like a "template", but what I talk about appears to me more like DAOs??
Or they don't have nothing to do, are just DAOs
I think I am a bit confused about all the different meanings of Model, ViewModel etc, in the different design patterns.
I am hardly trying to understand right MVC,MVP,MVVM and DDD and I think sometimes I am mixing terms...?
First, try to not "mix" things from different patterns, ViewModels are for MVVM, and you NEED ViewModels if you want to implement MVVM (ASP.Net MVC uses something called ViewModels, but it is not the same than the ViewModels in MVVM design pattern)
The ViewModel is like a model for the View. The ViewModel work is to "convert" the Model(s) to something the View can understand.
You can have one o more models (or none) and use it in the ViewModel, you have a ViewModel for each View.
In your example (a datagridview) you can have a model that will represent the data in a datagridview, a DTO if you want, and you can have a property in the ViewModel, a List and you will fill with data loaded from the database. In the View, you will bind that property (the list) to the dgv datasource.
Think that the ViewModel is something like the code behind of the view, but you are working with properties and commands that will be binded to controla in the view.
I've been doing a lot of research on different design patterns and I'm trying to determine the correct way of doing this.
I have an image uploading MVC app that I'm developing which needs to process the image in several different ways, such as create a thumbnail and save a database record. Would the best way to approach this be via a flyweight pattern? Using this as an example:
var image = new Image();
List<IProcessors> processors = processorFactory.GetProcessors(ImageType.Jpeg);
foreach(IProcessor processor in processors)
{
processor.process(image);
}
I have second part to this question as well. What if the processor has smaller related "sub-processors"? An example that I have in my head would be a book generator.
I have a book generator
that has page generators
that has paragraph generators
that has sentence generators
Would this be a flyweight pattern as well? How would I handle the traversal of that tree?
EDIT
I asked this question below but I wanted to add it here:
All the examples that I've see of the composite pattern seems to relate to handling of values while the flyweight pattern seems to deal with processing (or sharing) of an object's state. Am I just reading into the examples too much? Would combining the patterns be the solution?
I can at least handle the second part of the question. To expand a tree (or a composite), use simple recursion.
void Recursion(TreeItem parent)
{
// First call the same function for all the children.
// This will take us all the way to the bottom of the tree.
// The foreach loop won't execute when we're at the bottom.
foreach (TreeItem child in parent.Children)
{
Recursion(child);
}
// When there are no more children (since we're at the bottom)
// then finally perform the task you want. This will slowly work
// it's way up the entire tree from bottom most items to the top.
Console.WriteLine(parent.Name);
}
What your describing could have some flyweights representing each of those nested classes. But in this case that would be more of an implementation detail. In my experience, flyweights are usually called for at the architectural level or implementation level but rarely as an element of design.
Consider this class -
public interface IMyData {
IdType MyId { get; }
byte[] BlobData { get; }
long SizeOfBlob { get; }
}
public class MyData : IMyData {
public IdType MyId { get; private set; }
public byte[] BlobData { get; set; }
public long SizeOfBlob { get { return BlobData.LongLength; } }
}
}
In your multi-tiered application, this object needs to travel from the source database, to a manager's IPhone for approval based on the blob size, and then to an accounting system for billing. So instead of transporting the whole thing to the IPhone App, you substitute the flyweight:
public class MyDataFlyWeight : IMyData {
public MyDataFlyWeight(IdType myId, long blobSize){
MyId = myId;
BlobSize = blobSize;
}
public IdType MyId { get; set; }
public byte[] MutableBlobData { get {
throw new NotImplmentedException();
}
}
public long BlobSize { get; private set; }
}
}
By having both implement IMyData and by building the system with the interface and not the concrete type (you did this, right?!), then you could use MyDataFlyweight objects from the IPhone App and MyData objects in the rest of the system. All you have to do is properly initialize MyDataFlyweight with the blob size.
The architecture which calls for an IPhone App would dictate that a flyweight is used within the IPhone App.
In addition, consider the newer Lazy<T> class:
public class MyData : IMyData {
public IdType MyId { get; private set; }
private Lazy<byte[]> _blob = new Lazy<byte[]>(() =>
StaticBlobService.GetBlob(MyId));
public byte[] BlobData { get { return _blob.Value; } }
public long SizeOfBlob { get { return BlobData.LongLength; } }
}
}
This is an example of using the flyweight purely as an implementation detail.