I am building a software where I have users who are responsible for managing contracts. Each user can only see the contracts that they are responsible for.

Now, I want to implement a share functionality where a user can decide to share some of the contract details with another user, so the other user can now see in his contracts list a shared contract.

But first, I want to make sure that I implement this correctly in terms of the database.

So at the moment, I have the following with regards to the relation between the users and contracts:

user (1) manages contracts (1..*)

And to implement the share functionality, I added the following:

user (0..*) can see contracts (0..*)

Which resulted in a new table that I called SharedContracts. This table will store the userID of the user who will now have access to the contract and contractID of the shared contract.

So what will happen now is that whenever user A decides to share his contract details with user B, the SharedContracts table will be used to store this data.

And the next time user B logs in, the system will check if he has a shared contract by querying the SharedContracts table. The the system will select all contractIDs that are associated with his userID.

I want to know if this is the correct way to implement a functionality like this? Is there any other way? Can I run into some problems if it stays like this?

There is no single correct way to implement a feature like this. There are multiple ways to do it (yours is one of them) and which one you should use depends to a very large extent on the details of how the feature is supposed to work in your situation.
– Bart van Ingen SchenauMay 9 '17 at 10:58

3 Answers
3

I want to know if this is the correct way to implement a functionality like this? Is there any other way?

OK so far (given the limited information) but the design is incomplete so I would not say it is definitely correct. Design the functionality, the class design. When you have all the requirements covered then look to the database in detail.

I'm not saying don't think about the database. But you should be designing classes and their interactions. This will inform the database design; it should not be the other way around.

I try to think of the database as 'an implementation detail'. In other words the specific database and its details are essentially irrelevant to class functionality design.

-1 for the "database as an implementation detail". The DB is very often (read: default unless business specific constraints do not allow this) the single source of truth in an application. The rule "crap in, crap out" will apply if you have a broken DB schema. Business rule are more important than class design considerations. All previous paragraphs are correct, though, so I didn't actually downvote.
– TiboAug 9 '17 at 7:18

1

"DB is an implementation detail" If it's good enough for Uncle Bob it's good enough for me. And at least, for the purposes of "maximize cohesion and minimize coupling" it's a good way to think about it.
– radarbobAug 9 '17 at 17:26

Your design seems fine, but I believe there is a way to improve it by making it more abstract.

As I understand it, you make a difference between managing a contact and viewing a contact. This difference leads to different behavior as well:

In the case of managing a contact, (1) one and one only person can (2) modify and share a contact,

In the case of viewing a contact, (1) zero or more persons can (2) view, but neither modify, nor share a contact.

This looks like a permission-based system, with a read, read-write and allow-others-to-read roles over an object, with one difference: the number of persons which could be assigned to the roles, since you've set an arbitrary limit of 1..1 for the write permission, by further blocking the ability for two users to manage a contact.

Unless in this particular business domain, it would make no sense for two users to manage a contact, you shouldn't do that.¹ What is important is not some arbitrary technical considerations, such as “But how would I handle a case where two persons modify the same contact at the same time?” What is relevant is exclusively the business domain.

Copying the permissions schema would lead to a slightly different set of tables. You'll still have your Users and Contacts, but now, you'll also have a Roles table, and a Permissions table which would ensure a (n..n) relationship between the previous three tables, meaning that you would be able to set in a single table a relation such as:

User 123 has a permission read-write on contact 456.

¹ I can imagine a medical system which was originally designed with a core concept that a patient medical record can be managed by only his doctor. This could quickly show its limits, since it is not unusual for a doctor to work conjointly with a colleague, or have an intern, or be temporarily replaced by another doctor.