What to do if client can be both PF and PJ?

Asked

Viewed 7,111 times

28

I’m developing an object-oriented system. I need to keep a customer record. It turns out that these clients can be both natural and legal persons. If clients were just legal persons it would be easy: I would create an abstract class PessoaJuridica and the client class would inherit from it and implement other specific members. If the customers were only natural persons they would be analogous, inheriting from a class PessoaFisica.

If a client, however, can be any one of them gets complicated. My first idea was to have two classes ClienteFisico and ClienteJuridico each inherited respectively from PessoaFisica and PessoaJuridica. But that didn’t seem like a good idea.

Then I thought of a second option: define Cliente as a natural person at all times and then create a class Empresa, a customer may own none or several companies. Thus, if there are no companies, the only relevant data is the personal data of the client. If there are companies, then we have the personal data of the person responsible for it and I enclose a list with the information of the companies.

What I’d like to know is: is this second approach I took a standard approach? I say this in the sense that it is a common approach to dealing with this type of situation. There are better ways to model concepts such as this in object orietnation?

  • 3

    Maybe a reading of this answer help you.

  • 3

    hmm... maybe PessoaFisica and PessoaJuridica inherit from Pessoa, and Cliente has a Pessoa

2 answers

29


First: why does it need to be object oriented? There will be some gain in this way?

PJ and PF are separate entities

The second approach is completely wrong since if the client is a legal person he cannot be confused with a natural person who owns companies.

It could even be in a fictitious model or in a very specific case where the client really is the physical person and the relationship is with his companies, but in the real world is not usually the case.

The role of persons in the organisation does not define a new external entity

Perhaps you are more distant than you think of a solution. I ask you another question: is the customer also a supplier, and/or is a bank that you operate, and/or is a representative, and/or is a carrier. How do you arrange it?

Then you start to question whether a client is an external entity. Maybe client is just a feature, a property, an attribute, a role (role) of a business partner who may be a natural person or a legal person. And this feature has several details.

If it is to use object orientation then it has to model correctly. And I warn you that it is not always easy to do this in real applications. For this reason it is common for people not to seek purity of paradigm.

It is not possible to treat PJ and PF as a single entity to facilitate?

Maybe you’ve already begun to imagine that legal person and natural person are so different things that you cannot try, by maintaining a correct model, to make of them a single entity that has both characteristics. Already imagine that there really is a class, and therefore there will be objects, which are physical persons and there is a another class defining what a legal person is.

You begin to understand that PessoaFísica and PessoaJurídica are concrete concepts supported by legislation. And that such persons may have a specific business relationship at a given time (which may be permanent as well), classified as clientele, supply, representation, etc.

There are common features between a physical person and a legal person. So an abstract class can be interesting. This class would be Pessoa. Person is simply something that does not exist concretely. Note that in this example I am not speaking of person as a human being. In this case Pessoa is only the basis of characteristics for the classes derived from it. It may not even be limited to the natural and legal person. I have seen case of foreign person being used too, but does not work in any situation.

Correct modeling

I can’t answer if the approach is the standard because I don’t have the data for it, and I doubt anyone does. I also don’t know if it’s relevant.

If the intention is to make the correct model, look for the pattern, it does not guarantee the objective. My experience is that the pattern of what people often do is not the right thing to do.

I myself make mistakes in everything I have no experience. And in several cases the correct would complicate the design of unnecessarily applying.

Substantiating a little more

See how a bank (financial organization that you have current account) works. He has completely different registers and contracts for individuals and legal entities. Why does this happen? Because banks have departments or consultancies of Organization and Methods that define entities and processes correctly. They are not based on the lay opinion of programmers or company owners, as is often the case in the vast majority of cases.

It is much more difficult than it seems to correctly define what each entity is and what its characteristics, behaviors, relationships, etc. And there is no standard model. What works well in one situation does not work or complicates another.

And I’m talking about the conceptual model considering only business rules. Nor have I included mechanisms for the functioning of the application when dealing with a legal person. Because you are speaking in general terms, you have not given any parameter of how the application works.

Composition

You can create a class in which you have the characteristics of a natural person and a legal person. The most common way to do this is through composition. That is, you will have general data that works well, no matter if the person is physical or legal, and will have some internal object that will hold, externally, concomitantly or not, the specific data of the natural person or legal person.

But this is an approach that denies the main feature of object orientation (which can be a good one). Although I think you start creating classes franksteins in this case. A class that has penduricalhos depending on a property? I don’t see with good eyes until I find a plausible reason for it to exist, but there are cases for it.

The link posted by bfvaretto is very interesting to give a better idea on the subject.

And the answer from utluiz shows some examples of classes that can be used to make the composition.

User Experience

It is possible that you can not or do not want to leave this entity division exposed on the registration screen (and other locations of the system, but I will speak only of the registration screen to simplify).

It is understandable that this abstraction model created in the system is not in the interest of the user, that he does not wish or should not understand how it is organized.

But one thing does not prevent the other, the solution of the model is one and the solution of the UI is another.

You can ask to make the registration screen as if it were something unique for both types of person. One of the first fields can be the selection of the type of person, which will probably modify a part of the screen (possibly a tab) to adapt to the data of individual or legal, according to the selection. This is an interesting case to use composition.

Internally, in your business rules template, you will be using a class PessoaFísica OR PessoaJurídica but the user is not seeing this.

In the same way that you can ask him to register a customer on one screen, a supplier on another, etc. He thinks he is making separate registrations to the bottom, internally, be a unified register. When the user accesses a screen, he is preselecting one of the attributes of the class. For example, if he enters the client register, the property ÉClienteis set as true. If he then tries to register the same company as a supplier, the system will warn that there is already registration and only ask if he should activate the partner to be a supplier, marking in the class the property ÉFornecedor as true.

Of course, in a model organized this way, you can have attributes that only a customer should support, or other attributes that only an employee has (which can be a business partner too, a salesman for example). But this is another problem :) But if you have paid attention, read the related answer, you should already imagine how to solve.


You didn’t ask, but if you want to know what I think of the model adopted by virtually every system on the market, including the big and famous systems (one of which I was even part of the development since its inception), I say: amateurs! (of course this is a simplification, there are "plausible" reasons for "making that mistake").

And there is another question. With the advent of microservices modeling has become another. In general, each microservice has all the characteristics necessary for the object. It looks beautiful, but it’s one of the hardest things to do right. One of the reasons I say to get away from this architecture as much as you can. And almost everyone can, literally.

  • 1

    What would be the "model adopted by virtually all systems that exist in the market"?

  • 7

    It is this confusing model in which individual and legal entity is the same entity, but a customer is something totally different from a supplier. It’s a model created in the 1960s because the mechanism was more important, computers couldn’t deal with abstractions beyond the systems being very simple and because people were naive and didn’t understand the problems either. Unfortunately it was perpetuated. And to this day it remains present and teach people to model wrong.

23

There is no absolute answer. Depending on the scope of the application, the business domain and requirements, concepts of Cliente and Pessoa can vary enormously.

The first step in solving your question is to define the concepts of these entities, their attributes and uses. For example, on your system, what is the difference of a PJ or PF client? The two types of client will be used in the same functionality?

If in your PF and PJ system you have virtually the same attributes, ranging from one CPF to the other CNPJ, then one approach is to use a generic attribute numeroDocumento and differentiate CPF from CNPJ by content size or by an auxiliary field tipoPessoa. In this case, you have only one entity Pessoa varying only one attribute.

If PF and PJ are used in distinct functionalities, that is, they are not interchangeable, and do not have several distinct attributes or relationships, create two separate entities. Don’t waste time looking for similarities and hierarchies where it simply isn’t necessary.

On the other hand, if PF and PJ can be used in the same functionality, but this only needs access to some common attributes, then you can use a interface to solve the problem. Let’s assume that there is a method that receives a Pessoa and access her name and phone. It is not necessary to create an abstract class and use inheritance to use polymorphism in this case. Create an interface Pessoa and have PF and PJ implement this interface, which can contain common attributes only.

Now, going a little in the direction of what the @Maniero put in its great answer, for the case of a more general register involving various types of people, unfortunately most current systems are far from serving as a parameter for good practices. The different types of people can be agents in different systems, i.e., a natural or legal person can be a seller, buyer, customer, supplier, guarantor (who provides a guarantee), insurer (who provides insurance) and so on.

In this more general context, particularly, I would model a database as follows:

  • Table Pessoa with id independent of type or document, and tipoPessoa
  • Table PessoaJuridica with attributes of PJ, key CNPJ and FK to Pessoa
  • Table PessoaFisica with attributes of PF, RG key or CPF and FK to Pessoa
  • Table Fornecedor with vendor attributes, code and FK for Pessoa
  • Table Garantidor with guarantor attributes, code and FK for Pessoa
  • Table Cliente with client attributes, code and FK for Pessoa
  • And so on, for every "form" that a Pessoa can take over in my domain

Mapping this to an object-oriented language will depend on usage and relationships with other entities, but a generic border would be to have a class Pessoa no relationships and then PessoaJuridica, PessoaFisica, Fornecedor, Cliente and the rest with an attribute like Pessoa (composition). All these classes could implement an interface with the method getPessoa() so that they can be used polymorphically in so-called methods.

Note: I am not saying that this is the best approach, nor that it is a good approach. These are just a few ideas, but I never got to test them in practice because I didn’t develop a system from scratch with these concepts.

  • 3

    It’s certainly a good approach. If it’s for his situation it’s harder to say :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.