Extends Entity vs Extends Model in loopback4 - node.js

What is the Difference between extending Model vs Entity in loopback4?
#model
export class Todo extends Entity {}
#model()
export class Todo2 extends Model {}

From https://loopback.io/doc/en/lb4/Model-generator.html
An Entity is a persisted model with an identity (ID).
A Model is a business domain object.

Entity: A domain object that has an identity (ID). Its equality is based on the identity. For example, Customer can be modeled as an Entity because each customer has a unique customer id. Two instances of Customer with the same customer id are equal since they refer to the same customer. For example, this is how a Customer can be modelled::
Model: A domain object that does not have an identity (ID). Its equality is based on the structural value. For example, Address can be modeled as a Model because two US addresses are equal if they have the same street number, street name, city, and zip code values. For example, this is how a Address can be modelled::
From:
https://loopback.io/doc/en/lb4/Model.html#overview

Related

Aggregate or entity without business attributes

Regarding below excerpt, concerning cqrs and ddd, from Patterns, Principles, and Practices of Domain-Driven Design by Nick Tune, Scott Millett
Does it mean that domain model on command side can omit most of business attributes ?
How would it look like for eg Customer Entity?
Could Customer entity omit FirstName, Surname etc?
If so, where would these business attributes be? Only in read model in CustomerEntity?
Or maybe apart from CustomerEntity containing all business attributes there would also be CustomerAggregate wrapping CustomerEntity with 1:1 relation, and command object would operate on CustomerAggregate? (seems strange to me).
What does it mean "Customer entity desn't make sense"?
The text you pointed means that you do not have to model a reusable Entity for your whole system or even for your whole bounded context (Do not model reusable real life things). Doing this is a bad design.
You have to model an Aggregate that performs an action. You feed the Aggregate with only, and just only, the data needed to perform that action and the aggregate response, the changes the domain suffered, is what you have to persist.
Why Entities and V.O.'s then?
To model consistency, encapsulation and decoupling is the basic part but these are implementation details. For DDD what matters is that are different roles (or concepts).
When feeding the aggregate (constructor, function call parameters, etc) the aggregate has to know if it is working with entities and/or with V.O. to build its response.
If the domain action means a change in an attribute of a entity (something with unique identification in your whole system) the response of the aggregate (once all rules and invariants has been checked) should include the new attribute value and the identification of that entity that allows persist the changes.
So, by default, every aggregate has its own entity with the unique identification and the attributes needed for the aggregate action.
One aggregate could have a Customer entity with ID and its Name.
Another aggregate could have a Customer entity with ID and its Karma points.
So every aggregate has its own inner Customer entity to work with. When you feed an aggregate you pass Customer data (i.e. ID and name or ID and Karma points) and the aggregate treats that info as a entity (It is a matter of implementation details if there is a struct, class, etc internally to the aggregate to represent the entity).
One important thing: If you just need to deal with entities ID's then treat it as a V.O. (CustomerIdentityVO) because the ID is immutable and, probably, in that action you just need to write this CustomerIdentityVO in some field in persistence, not change any Customer attribute.
This is the standard vision. Once you start to identify common structures relevant to several aggregates or one aggregate that can perform several actions with the same data fed you start to refactoring, reusing, etc. It just a matter of good OOP design and SOLID principles.
Please, note that I am trying to be higly above of implementation details. I know that you almost always will have unwanted artifacts that depends of programing paradigm type, chosen programing language, etc. but this approach helps a lot avoiding the worse artifact you could have.
Recommended readings:
http://blog.sapiensworks.com/post/2016/07/29/DDD-Entities-Value-Objects-Explained
http://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-1
http://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-2
https://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-3
and
https://blog.sapiensworks.com/post/2016/08/19/DDD-Application-Services-Explained
for a complete puzzle vision.
If you are using Event Sourcing then it's true that you can model aggregates without adding attributes that they don't need for implementing the business logic.
Here's an example:
class Customer {
public Guid ID { get; private set; }
public Customer(Guid id, firstName, lastName, ...) {
ID = id;
this.AddEvent(new CustomerCreatedEvent(id, firstName, ....);
}
public void ChangeName(firstName, lastName) {
this.AddEvent(new CustomerRenamedEvent(this.ID, firstName, lastName),
}
}
Custom only has ID attribute because it needs it to add it to every event that it generates. FirstName and LastName are omitted as they are not needed even when ChangeName method is called. It only records an event that this happened. If your logic requires the FirstName then you can add it. You can omit any properties that you don't need.
Your Repository in this case will save only the events and won't care about the values of the attributes of the Customer.
On the Read side you will probably need these properties as you will display them to your users.
If your aggregates are not event sourced, then you probably will need more attributes on your aggregate to implement it's logic and they will be saved to the database.
Here's an example:
class Customer {
public Guid ID { get; private set; }
public string FirstName { get; private set; }
public string LastName { get; private set; }
public void ChangeName(firstName, lastName) {
FirstName = firstName;
LastName = lastName;
}
}
In this case your Repository will need these properties as it will generate a query to update the database with the new values.
Not sure what "Customer entity doesn't make sense" means.

Can I create multiple identity tables in ASP.NET MVC?

In my project, Admin adds Instructors, then each Instructor adds his students. When they are added, they'll receive an email asks them to complete registration .
I have the following classes in my project :
1-Student class
Student: int id, int Registry number, int grade, string password, string email, string name
2-Instructor class:
Instructor: int id, string name , string email , string password
3-My database context:
public class InstructorContext:DbContext
{
public InstructorContext() : base("InstructorContext")
{
}
public DbSet<Instructor> Instructors { get; set; }
public DbSet<Student> Students { get; set; }}
When a user loges in , I must determine whether he is an Admin or Instructor or Student. Do I have to use role-based authentication? I already have 2 separate classes for different roles. Is it possible for both of them to inherit from IdentityUser?
No, you cannot have multiple user tables with Identity, at least not technically. All the other core components of Identity (roles, claims, logins, etc.) are setup with foreign keys to one user table.
For your scenario here, you should use inheritance. For example:
public class ApplicationUser : IdentityUser
public class Instructor : ApplicationUser
public class Student : ApplicationUser
By default, Entity Framework will create the one table for ApplicationUser and add a Discriminator column to it. This column will have one of three possible values: "ApplicationUser", "Instructor", and "Student". When EF reads from this table, it will use this column to instantiate the right class. This is what's known as single-table inheritance (STI) or alternatively as table-per-hierarchy (TPH). The main downside to this approach is that all of the properties for all of the classes must be represented on the same table. If you're creating a new Student for example, the columns for an Instructor would still be on the record, only with nulls or defaults for those values. This also means that you can't enforce a property on something like Instructor be required at the database level, as that would prevent saving ApplicationUser and Student instances which are unable to provide those values. In other words, all your properties on your derived classes must be nullable. However, you can always still enforce something like a property being required for the purpose of a form using view models.
If you really want to have separate tables, you can somewhat achieve that goal by changing the inheritance strategy to what's called table-per-type (TPT). What this will do is keep the table for ApplicationUser, but add two additional tables, one each for Instructor and Student. However, all the core properties, foreign keys, etc. will be on the table for ApplicationUser, since that is where those are defined. The tables for Instructor and Student would house only properties that are defined on those classes (if any) and a foreign key to the table for ApplicationUser. When querying, EF will then do joins to bring in the data from all of these tables and instantiate the appropriate classes with the appropriate data. Some purists like this approach better as keeps the data normalized in the database. However, it's necessarily heavier on the query side because of the joins.
One last word of caution, as this trips people up constantly dealing with inheritance with Identity. The UserManager class is a generic class (UserManager<TUser>). The default instance in AccountController, for example, is an instance of UserManager<ApplicationUser>. As a result, if you use that instance, all users returned from queries will be ApplicationUser instances, regardless of the value of the Discriminator column. To get Instructor instances, you would need to instantiate UserManager<Instructor> and use that for your Instructor-related queries.
This is especially true with creating users for the first time. Consider the following:
var user = new Instructor();
UserManager.Create(user);
You might expect that the user would be saved with a discriminator value of "Instructor", but it will actually be saved with "ApplicationUser". This is because, again, UserManager is an instance of UserManager<ApplicationUser> and your Instructor is being upcasted. Again, as long as you remember to use the appropriate type of UserManager<TUser> you'll be fine.

Domain object with aggregate fields

I have domain object like this:
class Customer
{
string FirstName {get;set;}
string LastName {get;set;}
DateTime DateOfBirth {get;set;}
}
Product team told me: We have to get customer by ID. Customer has information like FirstName, LastName, DateOfBirth, Age and blank fields. Age and blank fields can be calculated.
There is no application, just API. Who consumes this API doesn't matter.
Q: If I follow Domain Driven Design how domain class Customer looks? Where I put fields like Age and list of blank fields (for every Customer)? How business logic class looks like?
I think you have an anaemic model going here. The age should be implemented completely in the Customer class. So that to access the value, you do, customer.age. The blankfields might be a concept that needs it's own entity/domain, because a "Customer" cannot have a "blankfield"; the language doesn't fit/make sense. If you need the "blank fields" to exist as part of a customer object though, consider using a value object inside the customer object as well.
You don't need the service doing all that you have it doing. The only reason the service might be involved in this is if there's no way you can have your entity doing the work because of an external dependency or possibly complexity.
So, your service constructs your database from your persisted data and that's the end of it's involvement. In fact, you should probably be using a repository for re-constituting your object (instead of a service).

Is this how to structure classes for DDD?

Assume I have the relationship where every customer has an address (which in this case, is an entity), like below:
Customer{ Id, Name, MyAddress (instance of Address) }
Should I be allowing a structure that exposes the following option:
MyCustomer.MyAddress.Street = "Pine Street";
CustomerRepository.Save(MyCustomer);
Should this cascade a save, both for the Customer class and for the Address class? Or, is it better to perform the following:
MyCustomer.MyAddress.Street = "Pine Street";
AddressRepository.Save(MyCustomer.MyAddress);
Unfortunately, Address really is a value object, but I cannot make it interchangable like DDD requires as the Id tag is present; for example, if I did the following:
Customer1.setAddress(Customer2.getAddress());
Both Customer1 and Customer2 now have the same binding to the same record, which is dangerous.
None of your samples is DDD. Each one is simple CRUD.
Don't "set fields". Do meaningful operations.
customer.MoveTo(new Address(...))
customer.FixAddressTypo(new Address(...))
Repositories are for aggregates, not any entities. Identify your aggregates. http://dddcommunity.org/library/vernon_2011/
Why not map the Addres value Object as a bunch of fields in the Cutomers table? You don't need separate table just because you have a separate class.
Value objects should be immutable.

Multiple similar entities or use the same one in core data?

So I've got a Client entity that needs a relationship to a PhoneNumber entity to allow multiple phone numbers. And I've got an Employee entity that also needs a relationship to a PhoneNumber entity to allow multiple phone numbers. Should I create two separate PhoneNumber entities or can I somehow use the same entity for both?
I would create a parent entity called Person for your Client and Employee entities. The Person entity would have a relationship to the PhoneNumber entity.
Inherited entities have the same attributes and relationships as their parent entity. Of course you can add attributes and relationships to the "child"-entities as well. I omitted that in the screenshot.
Something like this:
you can configure the parent entity in the core data inspector in the right side pane.

Resources