Create code from Pattern Graph - c#

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?

Related

How does one search within C# classes without previously knowing what's inside?

I'm sorry if it's confusing, but I don't really know how to word my question.
My C# class is filled with data from API JSON response, it looks as follows:
[DataContract(Name = "user")]
public class User
{
[DataMember(Name="id")]
public int Id { get; set; }
[DataMember(Name="email")]
public string Email { get; set; }
[DataMember(Name="name")]
public string Name { get; set; }
}
I would like to do things like finding an user from User object list, based on some data I have.
There are tutorials made by Microsoft about working with classes, they imply that I know what's inside by storing just added element in a variable.
My issue is that I need to find the User (specifically id) using email - I don't know how to start on this one.
The other MS doc shows that I can just iterate through all elements of User, and then I suppose I could find the id with a simple if statement?... No way it's optimal, considering there are over thousand entries.

How to define aggregate in DDD correctly?

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;
}

C# Complex Property Setter option

I have an ASP.Net MVC 5 (C#) application and I'm giving my users the ability to like posts and comments.
for this I have a Model called Likes with the following Properties:
public class Like
{
public Like()
{
this.CreatedUTC = System.DateTime.UtcNow;
this.isActive = true;
}
public long id { get; set; }
public string UserID { get; set; }
public bool isActive { get; set; }
public LikeType Type { get; set; }
public DateTime CreatedUTC { get; set; }
}
Type is an enum and it can be either Comments or Posts. I've also added the following Navigation Property to both Post Model and Comment Model:
public virtual ICollection<Like> Likes { get; set; }
My question is, can I have a setter function in the above line of code where it would automatically set Comments and Posts for the Like type? I know I can use the Value variable in the Setter but using Google I couldn't find how to use it for complex types as I have above (Like).
I'm sure this would be a better way of doing this than in the repository manually set that enum every-time I'm going to save a like.
UPDATE:
Seeing how we're starting a nice little conversation about this Questions, I will throw another alternative in the mix.
How about two Tables with a base class of Like, one CommentLikes and the other PostLikes Seeing that the size of this table will grow really fast, I'm thinking separating them would possibly be a good thing, Right?
I'd rather drop the "LikeType" and either have Comment and Post entity in the Like entity and distinguish by one of them being null or introduce two new entities
public class CommentLike
{
public Comment Comment { get; set; }
public Like Like { get; set; }
}
which holds a comment and a like and PostLike which holds a Post and a Like. The Comment then looks like this
public Comment
{
public virtual ICollection<CommentLike> { get; set; }
}
Another alternative is to create separate tables for comment and post likes. While what you ask for is definitely doable I would recommend more verbose but simpler solution which will result in code that is easier to maintain and has less bugs. Is there any specific reason you want to have a LikeType property?
I had same problem but didnt encounter an easy way.
class Post{
public virtual ICollection<Like> Likes {set;get;}
}
class Comment{
public virtual ICollection<Like> Likes {set;get;}
}
Then:
class Like{
//....
}
You dont need a bi-directional relationship. Do you have a case where you need to query Likes table? and if you do, you will have to manage parsing it as ENUM somewhere which can be an extension method.
EF will create Post_Id and Comment_Id implicityly in your table design. You wont be able to query it but you wont need to. IN my experience i never needed to.
My question is, can I have a setter function in the above line of code
where it would automatically set Comments and Posts for the Like type?
I assume you are using T4 template or the classes that were generated by EF are partialthen you can extend it by creating another partial class and a wrapper property for Likes
// Backing field
private ICollection<Like> _likesWrapper;
public ICollection<Like> LikesWrapper {
get {
// Lazy loading
if(_likes == null)
{
// Just create a new list or load it from the database.
_likes = new List<Like>();
}
return _likes;
}
set {
foreach(var val in value)
{
//Set the comment and posts
}
Likes = value;
}

Stuck at how to proceed unit testing this business logic using tdd

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>.

What is the best way to handle creating, and updating Complex Datatypes in MVC3?

Ok I've been trying to figure out the best way to do this for a few days, but still haven't come up with a very elegant answer so am hoping I someone can point me in the right direction or give some peer review :)
Basically I have 3 classes (they are different and much more complex than these):
public class Person
{
int ID { get; set;}
string Name { get; set; }
virtual IEnumerable<Place> { get; set; }
}
public class Place
{
int ID { get; set;}
string Name { get; set; }
virtual IEnumerable<Thing> { get; set; }
}
public class Thing
{
int ID { get; set;}
string Name { get; set; }
virtual IEnumerable<Place> { get; set; }
virtual int PersonID { get; set; }
}
So basically you have Persons, who have many Places, which can have many Things which can also appear in multiple Places (trying to reduce having to store duplicates of Things) but only for that Person
What is the best way to setup my ViewModel to handle this? Should I just create everything by itself using Ajax and Json (what I've been doing) or is there a way to handle this type of relationship in a ViewModel and single post back to the server?
Currently I'm doing the following:
Fill out Person form -> ajax save to server, get Person ID
Fill out Place form (including Person's ID) -> ajax save to server, get Place ID
Fill out Thing form (including Person ID and Place IDs in a delimited string
I know there should be an easier way to do this as its kinda bulky, but since its all query string I can't figure it out
You say "kinda bulky," but I think it tends to be more lightweight if you can build an object graph on a form in real time by using AJAX/JSON, probably against a RESTful API, somewhat as you describe.
The alternative is using script (jQuery, JSMVC, Knockout) to build a form and POST the whole sucker at once. I've had to do this in some situations where none of the data should be persisted until the whole graph is committed. The trick here is understanding ModelBinder and how it builds/updates that graph for you.
If this is what you were asking, I can expand on the key points of how ModelBinder deals with complex object graphs and collections.
I answered a similar question about how to handle this using interfaces and partial views.
How to create Asp.Net MVC 3 view model

Categories

Resources