I have a method that I give a list of car movements (Operation class) in a parking lot (Entries,Exits) each movement has a related cars list (OperationVehicle class). This method should result what I called cars log. It lists all cars, at what time entered what time exited and the duration for each one.
I am a bit lost on what things to test first. An answer to this question would be like a tutorial for me.
How can I proceed on unit testing this particular logic using tdd ?
public class Operation
{
public Operation()
{
OperationVehicles = new List<OperationVehicle>();
}
public int OperationId { get; set; }
public DateTime Date { get; set; }
public virtual OperationType OperationType { get; set; }
public virtual List<OperationVehicle> OperationVehicles { get; set; }
}
public class OperationVehicle
{
public int OperationVehicleId { get; set; }
public OperationType OperationType { get; set; }
public virtual Operation Operation { get; set; }
public virtual Vehicle Vehicle { get; set; }
}
public class CarLog
{
public int Id { get; set; }
public DateTime Date { get; set; }
public Vehicle Vehicle { get; set; }
public int StayLength { get; set; }
}
public IEnumerable<CarLog> GenerateCarsLog(List<Operation> CarStayOperations)
{
// not implemented yet
return new List<CarLog>();
}
What you have done so far is that you have modelled your domain in code (the relationships). But you haven't written much logic, so there's not much to test.
I wouldn't let your tests interact with these classes, at least not to start with. Rather, I would probably start somewhere around the user interface. Simulate the action that the user performs (and with user I don't necessarily mean a human being, but it could be another system). Test the behaviour, and do it as close to the boundaries of your system as possible.
Exactly what tests to write are hard to answer without more knowledge about the context. But I'll give it a try.
So what should the user be able to do with your system? For instance, write a first test where a car enters the parking lot and let the test assert in some way that the car is now in the parking lot.
But how would the user (or another user) know that the car successfully entered the parking lot? Is there, for example, some kind of user interface for the Car Log? Let your test's asserts look at that.
That would, however, be quite a large test to write, both including entering cars and checking the cars log. Perhaps better to start with the car log: just verifying that it is empty. Or perhaps there is an even smaller step you can start with?
My answer is a bit tentative, because that's what it is usually like: you learn and discover as you go.
A design note: Please don't expose lists from your classes (OperationVehicles). It totally breaks encapsulation. Add a Operation.AddOperationVehicle() method instead and return an IEnumerable<OperationVehicle>.
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;
}
I got a graph from which I need to set some propery in objects. Im adding an example on which I will explain it better:
Assuming I have the following class:
public class Person
{
public int Account { get; set; }
public string BirthCity { get; set; }
public string Name { get; set; }
public Family Family { get; set; }
}
Each Person that gets to the DAL will automatically be assigned with Status according to that algorythm. My real problem is much more complex, but this example does explain it well I think.
The graph describes scenarios and I need to translate it to code. I want my solution to be as flexible to changes as possible. Ofcourse writing ifs and switch case is the easiest yet its not a good solution.
One idea I had was creating an Xml file suting the scenarios, but I think that it might not be that good.
Does anyone have any Ideas about this issue?
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.
I have the below data model that constrains ItemTypes with a subset of Events. Each ItemType has a valid set of Events, this is constrained in the ItemEvent table. For example, a Video can be { played, stopped, paused }, an Image can be { resized, saved, or shared }, and so on.
What is the best way to reflect this constraint in the Entity model so that I can get compile time assurance that an Event used is valid for a particular Item? Specifically, I am refactoring the AddItemEventLog method:
public void AddItemEventLog(Item item, string ItemEvent)
{
//
}
Obviously, this is a contrived example, just trying illustrate-- it allows a developer to pass in any ItemEvent string they desire. Even if I create an enumeration based on ItemEvent resultset, there isnt anything in the entity model to prevent a developer from passing in ItemEvent.Resize with an Item of type Video.
I have Item as the base class of Video, and I have tried to override an enum but now know that is not possible. I am less interested in checking for the validity of the Event at runtime, as I already will throw an exception when the DB raises a FK violation. I want to nip it in the bud at coding time if possible :)
Currently have classes modeled like this but open to any modifications:
//enums.cs
public enum ItemType : byte
{
Video = 1,
Image = 2,
Document = 3
}
//item.cs
public class Item : BaseModel
{
public int ItemId { get; set; }
public ItemTypeLookup.ItemType ItemType { get; set; }
public string ItemName { get; set; }
}
//video.cs
public class Video : Item
{
public string Width { get; set; }
public string Height { get; set; }
public string Thumb { get; set; }
}
I think that Code Contracts may be the only way to enforce something like this at compile time. Outside of compile time checks, writing unit tests to ensure the correct functionality is the next best thing!
I'm still learning C# .Net 4 and this is my first WinForms so please be kind.
Continuing in my project, my financial DataFeed is streaming into my application by use of 'Asynchronous Sockets?'. Anyway, the data I am getting is tick per tick data, which is basically 1 order/transaction. So now I need to build bars with this tick by tick data, in particular Range Bars.
My problem is I don't want to go to the database and grab this data, so I am looking to do this in memory, like a list variable. Eventually, this system on the main server will do all the number crunching etc... and will have clients connected via Sockets to interrogate or set their own predefined algos on the in coming data and build their own charts using different ranges and indicators.
I wouldn't want to offload this to the client because I would like to keep the indicators technology proprietary.
How would I go about implementing this?
I already have my class called Tick
class Tick
{
public double Last { get; set; }
public double Bid { get; set; }
public double Ask { get; set; }
public double BidSize { get; set; }
public double AskSize { get; set; }
public DateTime TimeStampInternal { get; set; }
public int DTNTickID { get; set; }
public int UpdateTypeID { get; set; }
}
I'm thinking of a
Static List<Tick> Ticks
but I don't think this is the way to go because
I need to be able to hold only a certain amount of ticks and as new data comes in, old data gets thrown away, FIFO to keep memory usage down.
I will only be able to hold 1 Static List and I need something dynamic, e.g. have a List for each user that connects which would be identifiable to them only.
Please help me architect this correctly with best practices for speed and efficiency.
Sounds like a circular buffer is what you're looking for.
http://circularbuffer.codeplex.com/
Or perhaps a queue.
I hope that I correctly understand what you want, so here is very pseudocode :
public class User {
private UserTickList<Tick> _userTicks = new UserTickList<Tick>();
public void AddUserTick(Tick t) {
_userTicks.Add(t);
}
/*remove, update if need*/
}
public class UserTickList {
private List<Tick> _list = new List<Tick>();
public void AddTick(Tick tick) {
if(_list.Count == 10){
/*perform what you need*/
}
else
_list.Add(tick);
}
}
I repeat this probabbly will not compile, but just to give an idea what it can look like.
Hope this helps.