Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Contracts #3

Open
robsontenorio opened this issue Feb 10, 2022 · 11 comments
Open

[Question] Contracts #3

robsontenorio opened this issue Feb 10, 2022 · 11 comments

Comments

@robsontenorio
Copy link

robsontenorio commented Feb 10, 2022

Nice speak and thanks for sharing!

I got the idea about contracts between modules. But consider this scenario:

The Order module has a OrderLine product_id FK for Inventory and it is great interface usage on your example.

But, by “Laravel way”, to display an OrderLine with product names I would make OrderLine::with(“product”)->….

It would be a violation ? How do you deal with that ?

@avosalmon
Copy link
Owner

avosalmon commented Feb 11, 2022

@robsontenorio Thanks for watching my talk!
I think it's considered a violation since the OrderLine directly accesses the Product model which would expose all the properties and functionalities of the Product model. By accessing the Product model, the order module would be able to trigger whatever actions against the products table. e.g. update, delete
Also, when you test the order module, you won't be able to create a record for the order_lines table without creating a product. However, you shouldn't need to know the details of database tables of the inventory module when you are testing the order module so that the order module can be tested independently.

To deal with this, I would create a contract (i.e. interface) in the inventory module and the order module can get the product by calling the method. This will cause an additional DB query but we can keep the modules decoupled.

@ashourms
Copy link

I really enjoyed your awesome talk during the conference! well done!

I am wondering about the same thing, what if we have a model that is having relationships with many other models in different modules. When using Laravel eager loading "i.e. with method" you will get one collection that have all the related properties of other models.

So using the explained approach in your presentation, does this mean that we need to create a contract in each related module and get the related model information using those services?

@avosalmon
Copy link
Owner

avosalmon commented Feb 12, 2022

@ashourms Thank you for watching the talk!

Basically, a model shouldn't have relationships with models of different modules.
If a module needs to get data from different modules, we need to create a contract and get the required data using the contracts (i.e. interfaces). The contract should return a DTO instead of a related eloquent model to avoid exposing all the properties and methods to different modules. Alternatively, a module can dispatch an event and other modules handle it accordingly, which is a more decoupled approach.

If a module needs to get many different data from other modules, you might want to see if there is a better way to define your domain boundaries.

@ashourms
Copy link

Noted! Thanks for your feedback!

@inkomomutane
Copy link

Hi @avosalmon i liked you talk on laracononline of 2year ago.
And i face the same problem, i have a
Item model in Inventory model that has relation with Account Model (using sales_account_id) in General-Ledger modules.

How can i design the relationship in database of this tables in correct way for modules?
Or the database level isn't must relevant at this point, the modularization is on application level
Thanks.

@robsontenorio
Copy link
Author

robsontenorio commented Feb 19, 2024

TLDR: you will have additional DB query for each line you want to fetch , just like N+1

According its approach models can’t have relationships outside its module.

foreach orderline as line
line->product = ProductService::fetch(line->product_id)

@inkomomutane
Copy link

@robsontenorio

TLDR: you will have additional DB query for each line you want to fetch , just like N+1

According its approach models can’t have relationships outside its module.

foreach orderline as line line->product = ProductService::fetch(line->product_id)

But should the db structure change?

@robsontenorio
Copy link
Author

robsontenorio commented Feb 19, 2024

DB structure is the same. The change is about the fetch N+1 thing.

@inkomomutane
Copy link

Thanks

@avosalmon
Copy link
Owner

Hi @avosalmon i liked you talk on laracononline of 2year ago. And i face the same problem, i have a Item model in Inventory model that has relation with Account Model (using sales_account_id) in General-Ledger modules.

How can i design the relationship in database of this tables in correct way for modules? Or the database level isn't must relevant at this point, the modularization is on application level Thanks.

@inkomomutane Can I have more context about your modules? What kind of interactions would happen between the modules? The solution depends on the problem you are facing.

@inkomomutane
Copy link

Hi @avosalmon i liked you talk on laracononline of 2year ago. And i face the same problem, i have a Item model in Inventory model that has relation with Account Model (using sales_account_id) in General-Ledger modules.
How can i design the relationship in database of this tables in correct way for modules? Or the database level isn't must relevant at this point, the modularization is on application level Thanks.

@inkomomutane Can I have more context about your modules? What kind of interactions would happen between the modules? The solution depends on the problem you are facing.

Yap.

I have 2 modules
Inventory where are managed all items of purchasing, sales, etc...
and every item have transactions account, like sales account, purchasing account
like this

+---------------------------------+
| items |
+---------------------------------+
| purchase_account_id |
| sale_account_id |
....

+-------------------------------+
| accounts |
+-------------------------------+
| id ....

But the accounts are managed on General Ledger Module
And Items in Inventory module
am looking for best approach to design the database schema for that case.
Because in your point of view model classes of one module should not have relationships with another outside of.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants