Consider my scenario of a model consisting of two aggregate roots, Customer and Order as well as a "shared" entity Address.
Also note that Address is abstract has the following subclasses: PhysicalAddress, PostOfficeBoxAddress and PrivateBagAddress.
A Customer can have many addresses organized into some sort of address book.
Upon making an order a customer would select an Address from their address book to be used as a delivery address.
My initial thoughts were to share an address between the two entities, but I have since opted out as it will cause trouble with managing the respective invariants.
Another option I could go for is to create two hierarchies of Address, each for their purposes as a customer address or delivery address. This again doesn't seem right as there is a lot of repeated code.
How would I model this situation properly?
An entity is something that should be able to exist by ifself such as a customer or order. However an Address is not an entity, an Address is a value type and cannot exist on its own hence:
An Address can only exist as a value type that is aggregated within an entity
You can define your address hierarchy as a value type in your domain but many entities may use this.
We find that we come across these types of entities all the time such as Address, MoneyType etc.
Solution would be to create 1 Address hierarchy value type in your domain. Then any entity can have an Address as a property where applicable
Related
This question already has answers here:
How can you represent inheritance in a database?
(7 answers)
How to design a product table for many kinds of product where each product has many parameters
(4 answers)
Closed 1 year ago.
I'm trying to build a letter of statement request system using MySQL as its DBMS. I don't know if "letter of statement request" is the appropriate term, but the system is meant to provide simplicity for college students to request a letter of statement from their faculty or university; such as active student certificate, research permit, etc. I have started to make the system but now doubt whether the database structure (just part of it) is ideal.
Here's the overall flow of how the system works:
Student sends a request for a letter of statement to the system. There are many available types of letters, but they can only request one type at a time.
Each type of letter will require different data to input. For example, an active student certificate requires the data of the current semester of the student and the destination institute where the certificate will be used; while a research permit requires the data of research title, the institute/place where the research will be held, time of research, research subjects, etc. This is where the confusion and doubt hit me.
The requested letter will be then gets verified by officers and will be sent to the student if gets approved.
Here's the (partial) database structure in question (Tailored for simplicity)
letter_type
type_id (primary key)
description
letters
id (primary key )
letter_type (foreign key)
submitted_at
necessity
letter_position
status
active_student
letter_id (primary key, foreign key)
semester
destination_institute
research_permit
letter_id (primary key, foreign key)
title
institute
duration
subject
The letters table is used to record the overall data of the letter, including the id of the student, type of the letter, submission date, etc.
The two other tables, active_student and research_permit, are used to record the 'detail' data of the letter. Meaning that the data of a request for an active student certificate will be written in letters and active_student, while a request for a research permit is written in letters and research_permit
letters table will use its letter_type field to determine which table it should be referencing.
Finally, here's the question:
Is my database structure ideal? If not, what's the better approach available?
Additional context
I'm making the system using Laravel 8. The code for creating a new record of letters is easy because each type of letter is handled by a different controller. The difficulty comes when I want to make the code for retrieving a set of letters' records (for example letters sent by a student with id 'X001'). What makes it difficult is because I need to retrieve records from the letters table along with its 'detail' data in the referencing table of each record (there are more than just two types of letters actually).
Actually, I would like to ask about how to do this in Laravel. But before that, I want to make sure that my database structure is correct.
This is a very good question in my opinion. You are worried that in order to enter the data for a particular request you need a table for that request with all its obligatory (and maybe optional) columns. Every time you want a new request type in your system, you'll have to add a table for this and change the software.
This is one of the few cases where a key/value table might be an appropriate choice. Here is an example:
letter_type (letter_type_no, name)
letter_type_field (letter_type_no, field_name, is_obligatory)
letter_request (letter_type_id, student_no, date, status)
letter_request_field (letter_type_id, student_no, field_name, field_value)
Key/value tables are a nuisance to work with. If you have just one table for them the values must be strings for instance and dates and numbers must be stored in an agreed format. Validity checks are hard to implement. The list goes on. But for a new letter type, you just add that type to the letter_type table and list all required fields in the letter_type_field table, and all your queries and software can work with this.
Another and probably better approach, though, may be to use a NoSQL approach. E.g. store the field list in an XSD and use this in your app to have the student fill in a form that you store as XML. It's simpler, and there will be a person looking at the request anyway, so they can point out missing or wrong data.
Good evening,
I write you after days of "thinking": D
I'm working on a WFM system that allows you to manage activities from the field.
But now the request to manage several different activities forced me to redesign the whole DB.
Originally only 2 types of activities were handled (Installation, Failures) and all was managed by a single database table with all the columns of one and the other activity. The unused column for a task assumed the null value and was not shown via PHP.
Now I have to understand how to structure a db that has the following characteristics:
- the user can configure endless types of different activities (Installation, Failure, Gardening, Reclamation, etc ...)
- the user can configure infinite properties / attributes (Client name, Surname, Address, Expiration date, etc ...)
- for each activity can be associated many properties (certainly not all)
- each property plus being associated with many activities (certainly not all)
- each property can take as many values as it is applied (N ° values = property X activity to which it is applied)
- the user does not have to choose the table in which to insert the property, whether this is called "Customer cousin name" or "IBAN for payment"
Making a practical example I can have that the properties of customer registry are used for each activity, but maybe the property "Height grass" is used only for the activity "Gardening"
Can someone help me? Thank you
I always think that an address data is a value object since it is immutable and its equality is defined by the same data in all fields. For example, a billing address in a part of a payment and a shipping address is a part of an order or a fulfillment. When someone changes her/his address, a new address data is needed. But, every single sample code/application, I have run into, has an address data as an entity, which its DB table has its own ID. It would make a sense if a system wants to keep track of all addresses where all business activities/events occur. I, however, don't see such intention in those sample code/application. Do I miss something in the regard?
You can't generalize.
Examples are one thing, real world problems are another. You can't say that for all projects one solution fits it all.
I'll give you an example I had in a project conserning aggregate roots.
Logically and legally a subsidiary is an extension of its company, eg. Walmart has its HQ with tax number and everything and subsidiaries without tax number where the actual stuff is sold. Logically, for applying to a goverment funding or something similar, the HQ sends a request for its subsidiary. Here, Walmart HQ is an aggregate root and its subsidiary is a part of an aggregate in funding procedures.
This is a logical example.
What I had is that a subsidiary can legally apply for state funding without the knowledge of HQ! Therefor, HQ is not an aggregate root anymore, but a subsidiary is. It was extremely illogical, but those were the business requirements.
The point is the same with your value object question. Although you can use Address as an example that it is an entity or a value object, it is the requirements of the business that dictate what an address is, and not what is logical.
Pre-note: there are domains where an address should be an entity, like a mail service; we do not talk about those domains
From my experience, people tend to implement an address as an entity because of the persistence: it is easier to persist an address as a sub-entity to a relational database than to persist a value object because of the entities ID that act as primary keys in the storage table.
However, there are tactics that permit storing a value object as an database entity but still using it just as a value object, as it should be. Vaughn Vernon shows how to do this in his book, Chapter 6, sub-chapter Persisting Value Objects.
I have a database design requirement that is getting increasingly complex for me to figure the best way of approaching.
Currently, I have "contacts", and I have "companies". A company can have multiple contacts, but a contact can only belong to one company. This makes an obvious 1:n relationship. However, a contact does not have to have a company; mainly a residential/non-business customer (thus would be referred to as a "customer" on the front-end). This turns it into a 0:n relationship it seems.
The contacts table has a simple foreign key to the id of the companies table to establish this relationship.
The problem comes with storing addresses and phone numbers. Currently, the contacts table and companies table both store a single address and two phone numbers each (static columns). In most cases, the software simply mirrors the same data in both tables; the "company" data is shown as prevalent when it is available (aka the customer does not have the id of "0" for its company). This causes some confusion to the end user, and also has severe limitations.
I am in need of revamping this design in order to store multiple addresses (billing, ship to, etc), and of course as many phone numbers as I want. This is especially for companies that may have multiple facilities and one central billing office of course.
At first, I think of making the 1:n for the addresses against the companies table; however, the contacts also needs its potential separate data. This mostly gets complicated since a contact, as mentioned before, does not have to have a company, and could be a stand-alone. The company needs a master list of addresses for probably billing purposes, then the contact may need their own list of addresses for service and such. Or, the company could simply have all the addresses (could be best for statistics), and then the contact has only their primary address or something.
How can I go about putting this all together? Do I have one table for all contact/company addresses, or do I need seperate tables (contacts_addresses and companies_addresses)? I will of course use the same strategy for phone numbers.
The more I research, the more I get confused to be honest with so many answers and approaches. The leading one so far for my application sounds like this question. According to this, should I have the 1:n relationship with the companies table, and then a simple 1:1 relationship for the contacts? If this is the case, do I have contacts refer to the same table (and have a dropdown of the addresses linked with their company for a choice, and an option to make a new one), or have simple static columns in the contacts table?
An individual and an organization are concrete representations of an abstract Legal Party (This is called the Party Model).
Individual : Party
Organization : Party
An email address, web address, phone number, physical address can be thought of concrete representations of an abstract address.
EmailAddress : Address
WebAddress : Address
PhoneNumber : Address
PhysicalAddress : Address
An address can be unoccupied. A person can have multiple addresses. Multiple people can share one address.
Therefore there is a many-to-many relationship between Party and Address:
Party -< ContactMethod >- Address
Where ContactMethod has a role label, such as "Work", "Home", etc. The more specialized PhoneContactMethod might have an Extension column.
Suppose you have two objects, Person and Address and they have a relationship, that is a Person has an address. Obviously the person object has a reference to the address object but does the address object really have to know about the Person object? What gives that it has to be a two way relationship?
Thanks!
In this case it looks like your Address object doesn't need to have a relation to the Person object.
As a rule, you can think whether an object "needs to know" the other in order to work. A Person needs to know its Address, while an Address doesn't need to know the Person it belongs to.
"need to know" here reflects the need to interact with the object in a method.
It all depends on the use of the objects. If you have a situation where you must take an address and show (or use) its person (or persons) it will be a two-way relationship. But if you never need to access a person given an address then you will not need a two way relationship.
Other example: if those objects are associated with database tables and those table have a relationship (say Person.id == Address.IdPerson) then it will be useful to have a two way relationship in the classes for inserts and updates.
The only type of situation I can think of that it would be beneficial is if you had an external reference to an Address and you wanted to know who lived there. Even then, I think a separate associative data structure that maps Address -> Person would be a better design.
Other than that, in the relationship you describe there is no reason it has to be a two-way relationship. There's no rule that says an Address needs a reference to a Person.
They way to think about it is does my object depend on a property to exist. So in this particular scenrio, Person depends on an Address therefore it needs to know about the address details. The Address on the other hand does not depend on the Person hence can exist without knowledge of the Person.
If you need to access the person via the Address I would suggest implementing a function in the Address object that you can call which will retrieve the Person(s) relating to that particular address.
James.
In my opinion the Address object doesn't know about the Person object at all.
If it does then it interduces thight coupling to the system.
If you have to find a Person by it's Address you create a Pepole contianer that has a find method that searches by Address.
An Address doesn't have to know of the existance of Person, I think this is not logic in a real world: an address is just a group of information (say street, town, etc), it can be used by a letter or by a person, but in each case it still remain what it is, without knowing its surroundings.
It should only care of information strictly related to him.
What gives that it has to be a two way
relationship?
The only thing I can come up with that would be a motivation for an Address to know about other objects would be if you are in dire need of caching. Let's say you have some form of application where searches are made all the time. But that's pretty much it.
The complexity of this problem depends on the business domain and what you mean by address. In the majority of systems this is simplified to be a person object who has a relationship to an address object representing where they stay and if two people stay at the same address they address will be duplicated.
If you want to have a more complex real world model then consider changing to terminology to locations (which may even be represented spatially).
Considerations
A person may be related to zero or more locations (consider summer and winter homes)
A location exists regardless of having people related to it
If a person moves home consider changing the relation ( used to live at ) rather than the location. This provides a great deal of flexibility it the future
Multiple people can be related to the same location. This makes it very simple to find everyone who currently (or previously) stayed at a location
Storing locations and relationships provides great flexibility but it comes with an overhead, so you need to decide if your design needs this level of flexibility.