Heritage and Polymorphism

Asked

Viewed 1,655 times

14

I have the class Funcionario.

private String nome;
private int idade;

public function vender (Funcionario f)
{
  ...
}

I have the subclasses Gerente and Professor that inherit (extend) from Funcionario!

Manager

private String cargo;

Salesman

private String departamento.

I have an environment and would like to give access to both.

In this case, I think they should be created like this:

Funcionario g = new Gerente();
Funcionario v = new Vendedor();

Saving the sale in the database, what would be the object that would be saved that executed the sale?

Employee, Manager or Seller?

If you are an employee, when it is time to display the sale later and highlight whether it was the Manager or the Seller who sold it, what to do if Manager has different attributes of Seller and there is no table in the database called Employee with the attributes of Manager and Seller together?

  • 2

    public function?

  • Even if you’re just studying OOP, it would be nice for you to use a problem that you can formulate well. When you try to discuss the solution to a modeling problem that is not well defined it is easy to fall into endless ramblings that go around in circles and end up not adding much value. Note that it is not about knowing in depth all your needs to only then model, it is about knowing in depth a part of the problem, and from there model the solution for this part. If you want to update the question with more details about the problem I think we can help better.

6 answers

11


Several tables

There are two ways to solve this with several tables.

Related tables

There are also two ways to organize this way. This is the way normalized.

Don’t forget that if the employee changes roles, you will have to delete data from one table and create data in another. These function tables should only be directly linked to the employee table. Except in a very specific case, they should not be used in other parts of the application directly.

Inheritance

If you want to strictly establish the inheritance adopted in the classes, you will have to have a staff table. And it should have a table for each new descending class to create. This makes everything organized, it’s easy to extend the application with new employee roles, and it’s a little easier to fill classes and save their data into the database. Just be careful not to hurt the YAGNI or the KISS.

If you take inheritance seriously and do not want to have members of a derived class that are duplicated into another derivative without being inherited, then it is likely that you will need to create a class hierarchy to structure all members properly. This can become confusing, difficult to manipulate and is considered an error by almost all developers.

It gets complicated if you have to do something like this:

Pessoa
    Fisica
        Funcionario
            Comercial
                Gerente
                Atendente
                Vendedor
                    Principal
                    Auxiliar
                    PosVenda
            Administrativo
            Producao
        Cliente
    Juridica
        Fornecedor
        Banco

I made the hierarchy so simplified, could have more levels and obviously much more derived in each level.

But then will make the inheritance more or less (half-mouth)? Will you solve the main one and then resolve these other cases of grouping members in another way? That is, either it will have certain identical members that will exist in different derived classes without having a common ancestor, or it will have these members in the class Funcionario but will not be used by all derivatives?

Of course, the inheritance of these things can be obtained by interfaces (it’s easy in C# with properties, in Java 8 with standard methods or C++ with multiple inheritance), which would make it a little easier, but it would still be a bit confusing if you had many members like that. And the interface is not a solution for everything. Creating an interface without having a reason beyond the pure and simple grouping, can be an exaggeration.

So, are you going to make the inheritance in full or in half? Perhaps it is better to make the composition.

Relationship (composition)

Unless you use one object-oriented database (do not usually recommend), tables compose the objects and do not inherit them. So it may be more interesting to make a composition and not an inheritance in their tables. In a relational model objects are composed. When you try to have a relational database and an object-oriented model in the application you have a impedance.

There are two ways you can do the composition.

You can have a reference to the employee data in the function classes/tables and use the functions as a binding element in operations such as the sale you spoke about. There’s an answer showing how it does this. But I think it’s wrong. What happens if the employee changes roles? Do you have to change all the places where it was used? Who sold it was the seller or the employee? Well, there are cases that might even make sense to use the function. You have to analyze what you need.

Or you can compose an employee with a role (or more than one, eventually, depending on what you need). Note that this function, if done correctly, can be changed whenever needed. And this way allows working with the employee as a binding element in the sale.

Interestingly if it can only have one function at a time, using the employee makes a lot of sense. If it can have other functions and some of them can exist parallel to others but are disabled for use, it may be that keeping the function is interesting.

The question that needs to be asked is: the function has an official or the official has a function ()? If you answer right, you know what to choose.

Tell me how you’re going to use inheritance for an employee to accumulate functions! This is a classic mistake that people make when they close their eyes and think inheritance is everything.

Inheritance must be used when an object is a (is-a) another object with particularities. A manager is a employee, right? Or does an employee, at a given time, have the characteristics of a manager? He is a manager or he is a manager? In English it is more difficult to resolve this question :P

On the other hand a sale should have only sellers? Then who knows might be right to have the hierarchy or at least the composition in the function. That is, you will always put a salesman in charge of the sale. And eventually you can put his manager as co-responsibility for the sale. And this link must be made only with these two functions respectively. It cannot be any official. In this case an employee may no longer be a seller but there will still have to be an object for this to keep the whole model consistent, since sales were made with this seller. This is good or bad for you?

Think of it differently. If an employee leaves the company, he cannot be removed because he has several other objects that depend on him, but he is not an employee, you change him to "former employee" (and then you would have to have a base class for these two forms: employee and former employee) or kill him and have a property showing that he is no longer active?

And if a salesman works that long, he stops being a salesman and then he goes back to being a salesman. Should the two phases be considered different functions or should it be the same? All this helps define how it should be modeled.

Note that here I’m only talking about the composition, no matter who composes what, is not inheritance.

Separation of duties

This is another very adopted alternative in the past. Actually still very much used today because people learn the old way. It does not mean that this way is wrong and should not be adopted. It has its advantages... and obviously disadvantages.

In this template you have function tables that have all the employee data. So you avoid the composition, the inheritance, no problems with columns that should be null. No problems to create new functions.

Of course, the way to extend the application with new functions will be different. It is clear that in the sale or other locations you will have to say that it is the employee and somehow identify his function to know which table to fetch your data, either by a code pattern or by an explicit information.

If you have to change something in the model that is valid for all functions, you have to do this in all tables. And if you follow the same model in the classes, you have to do the same in the classes.

This may sound terrible, but it is not at all bad. If you consider that everyone commands to apply certain principles in OOP and one of them is the open-close, can be worse to change a class that is inherited than a class that will not be derived. Then we start to see that OOP has its flaws there.

A table

In the above form with multiple tables can have a loss of performance. Virtually every time you want employee information you will have to read two separate tables to get the general employee data and the job specific data.

To solve this you can assemble a single table of employees and in it have the data of all possible functions, leaving without data those that do not matter for the other functions of that employee.

This form has the problem of having a lot of columns that will never be filled, a lot of null. I’d have to take care of these things.

In addition it will be more difficult to carry the data from and to the database if it maintains the inheritance structure.

This form is not normalized but some cases it is better.

Depending on the case, do not rule out the possibility of making a single table and making the classes reflect this. Inheritance is beautiful on paper, but it’s not always the best solution in real applications. The same goes for normalization.

But this makes it difficult to create new functions because you would have to modify the database table to include the specific information. But you need to know whether this will be common or not. The problem is not so much changing the table, but the way to change the application can become more difficult if you make a "linguing".

On the other hand, the structure of inheritance or composition makes the application more complex. What difficulty do you want to deal with?

On sale

In the sale you will always keep the employee because it is always he who makes the sale, no matter his function.

Eventually you can have more than one person responsible for the sale. And then your application will decide how many can, and what roles they can have. It may be for example that you are a salesman and a manager always, or it may be any functions, or just sellers. Even if it is only possible to place seller(s), could still refer to a manager if there is this hierarchical information in the employee register.

When you have different information, you have to treat it differently. That’s what I said above, you will need to know where to fetch additional data. You certainly have employee role information in this table. So it’s easy to identify where to look.

If it adopts the decoupling itself, either by inheritance or by composition (that better decoupling and keeps more cohesive), to maintain consistency, the screens should be made in the same way.

Now think about this: in the application, how will you keep the person responsible for the sale? Probably the function, right?

If you do inheritance in the application (in the relational table does not give), will you use what in the entire application? The employee or the function (manager, seller, etc.)? There are cases for everything. When only importing the employees' parts, it will deal directly with itself that the concrete object is a manager or a seller. But in most cases it will deal with the derived classes with the functions. This can become confusing with respect to the database. If you know what you are doing, if you organize it correctly, you will have no problems. But if you make a mistake, you will be lost because of the impedance already mentioned.

Polymorphism can help or hinder this case.

Completion

What are you doing this for?

If it is learning to do everything object-oriented, follow this way, understand how to solve the relationship problem and the inheritance or prefer to make the composition that is still object-oriented.

If it’s a real application, think about what it might have in the future. Think about the ease of maintenance.

In applications that tend to be complex, which may have a lot of maintenance, have new functions added, it may be interesting to use the form of inheritance or composition and related tables.

In simple applications, which will be more or less static, which need low cost, ease of understanding of everything, having speed of access to data, doing something simpler is better, even if it is a design bad from a theoretical point of view.

The only way to know what’s right for each case is to have experience. Experienced people can help you but only if they know the whole situation deeply and are committed to doing the right thing. And I’m talking about quality experience, not quantity. There are people in their 30s doing this and doing it all wrong. Asking random people on the internet can give you general information to help you, but it won’t be the ultimate solution to your case.

If you set the class in a way, why should the table be different? You can, but you need to know why. And know the consequences of this.

One thing I learned when I was going to change something in the application and I have difficulty is that the initial modeling of objects was wrong. It’s very difficult to model right, to think of everything, but you have to do it right to facilitate maintenance, you have to understand the problem correctly, even the experienced ones don’t usually do this. I still make mistakes today after years of doing this, but not again after learning something new. This is the most important thing.

And you have to set aside the right way in some cases if you have other concerns like simplification or performance.

  • 1

    I think I have an error in that passage: "A table... This way, virtually every time you want employee information you will have to read two separate tables..."

  • @Cantoni not finished yet and I will review everything, but other than a typo in the next section, I do not know what error you are talking about. Can clarify?

  • I realized that it was in the same editing process. Inside the section "A Table", you left the excerpt that goes to "Several Tables"..

  • I think composition should be better than inheritance! I wonder if I post here a zip with my little design, some of you can take a quick look at the architecture! I’m coming from php so I’m picking up a bit. This project I’m doing is not commercial but just for learning the new language. Anyway, I’ll leave the link where the zip is with the project. http://www.funerariosaopedro.net.br/imwsaogotardo.zip. I thank anyone who can help!

  • @Cantoni you’re right, it’s very confusing this part, I improved. I haven’t finished yet but if you have something else just say.

  • @Carlosrocha probably does. In most cases it is the solution I would give. Posting the entire project is not possible here. The philosophy of the site is to solve specific problems, not general ones. Your question is good for the site standard, but asking to review your entire project is not. See [tour]. We can answer all your questions but need to be specific. See [Ask] and http://answall.com/help/on-topic.

  • Here is the project! http://www.funerariasaopedro.net.br/imwsaogotardo.zip The idea is only to revise the mvc architecture and model classes. Not the whole project!

  • Then the exit would even be the sale be held by an Employee. When displaying sales data a search should be made in the tables Manager and Seller which of them has the function equal to the function idFunctional of the table Funcio and then decide which object data to display.

  • Ah, it’s not the whole project, is yours a considerable part of it? Read what I’ve passed on to you. Specific questions are specific questions. Asking for review of the whole project or part of it doesn’t work. You got off to a good start by asking specific questions, don’t change the path that was good.

  • Fine. But anyway I will reread the answers published here and study a little more about inheritance versus composition to decide. Thank you all!

  • See how a simple question can yield? Imagine doing the whole revision you want.

  • @bigown, your answer was excellent. + 1 for her. I will prefer this question.

  • @Cantoni is not ready yet, I think the content is getting cool even, but the way is still bad.

  • @bigown, answers like that are not to be read just 1x. I’ve read a 3x and some more excerpts than others. It’s very dense (and it has to be, because the subject requires depth). The only suggestion is: put figures of the entities and their relations in the Database for each situation described. This will facilitate the understanding of each situation. In the end I say: this answer will be a source of excellent queries on the subject. Congratulations on your dedication!

  • @Cantoni is, I will try to do something in this direction.

  • is @bigown, it really can’t read just 1 time. This project is just a java startup that I’m doing on my own. I also read that there is the instanceof feature to solve this problem. But in view of what I read here I’m beginning to lean towards the composition in relation to the inheritance. What do you think?

  • @Carlosrocha I go even better the text, I had some more ideas today. But that’s it, the composition almost always works better.

  • @bigown. A doubt that crossed my mind. Would it be correct to use composition in scenes where inheritance is most conducive? For example. A Manager is an Employee. But an Employee is not made of Managers! Therefore, I think that doing idFunctioning in the Manager table, ie, composition, would not be consistent! What guidance gives me in this case?

Show 13 more comments

7

It all depends on how you map this heritage in the database.

Basically, there are two options. The first consists of using a single table for the entire class hierarchy. The second uses a table per class. Each has its advantages and disadvantages.

Below I will explore the two options based on the following class model:

Example:

Funcionario
    Nome
    Sobrenome

Vendedor herda de Funcionario
    Departamento

Gerente herda de Funcionario
    Cargo

A table for all class hierarchy

Doing everything in a table only avoids the need to perform joins, and simplifies CRUD (Create, Update, Delete) operations. However, there are some side effects, such as not being able to use the NOT NULL restriction in the child class fields.

The above hierarchy would be mapped to a table called FUNCIONARIO. This table would have the 4 fields above. However, only the field First and Last name could be NOT NULL. The rest, Department and Office, must allow, obligatorily, the value NULL.

To differentiate Employee, Seller and Manager, it is necessary to create a field in the table that will be used as discriminator. This is the field that will be used to know of which class is determined record.

Thus, this field can have the FUNCIONARIO value when the registration in the database represents a Employee, the SELLER value when a Seller and the MANAGER field when representing a Manager.

A table for each Hierarchy class

In this case, a table is created for each class, that is, a table for Employee, another for Manager and another for Seller. The ratio of the employee table to Manager and Seller is 1:1. In this approach, you preserve normalization and can use the NOT NULL constraint normally. However, there is a cost, since when recovering a Seller or a Manager, you will need to join. In addition, CRUD operations become more complex.

Modern Orms, like Hibernate and others, allow you to specify these two ways of performing mapping. They themselves decide, at the time of retrieving the record, what type of object will be created.

  • And how is the relation of the employee with his function in the second case?

  • Even @bigown, modeling the Function (Manager, Seller, etc.), as heritage of the Employee class also does not seem to me something consistent with reality. There will certainly be problems, because if an employee ceases to be a salesman and becomes a manager, it will be necessary to migrate it from one table to another. If there are other direct relationships with the Seller class, for example, then it is even more complicated. Anyway, my answer was more in the sense of explaining how OO heritage is mapped into a relational database than really focused on the context of the question.

  • I get it. The question is which one do you think you should use in this case you described.

  • I think a good way is to decouple the employee and the function. For this there would be a FUNCIONARIO_FUNCAO table that would store all the functions of an employee, the current(s) and the past(s). A flag field would be used to mark whether it is the current function or a passed function. In the end, this table would be the job history an employee has held in the company. What do you think?

  • It’s an interesting solution. It’s complex but when you want to solve everything right, you end up having to do these things. Of course I have not seen implementation, probably the details would vary depending on the situation, but it is more or less this even if it is necessary. Just one detail, "if it is one of the current functions, "may have more than one :) But still my doubt would be: the functions have an employee or the employees have (in) function(s)? That is, who will be FK of the other?

  • Yes, in this model the Employee could accumulate functions. : -) In this case it would be: An Employee can be in N Functions and a Function can be in N Employees. In the end, it is an Nxn relation between Employee and Function. In the FUNCIONARIO_FUNCAO table there would be two foreign keys (one for each table). They can repeat, because an employee can become a manager more than once, at different times. This all shows how complicated it is to model a problem. It is undoubtedly one of the most complicated activities that exist in software development.

Show 1 more comment

3

My suggested mapping would be like this.

public class Funcionario {
  private Long id;
  private String nome;
}

public class Venda {
  private Long id;
  private Funcionario funcionario; //relacionamento com o funcionario que fez a venda
}

public class Gerente {
  private Long id;
  private Funcionario funcionario; // relacionamento com as informações de funcionario do gerente
}

public class Vendedor {
  private Long id;
  private Funcionario funcionario; // relacionamento com as informações de funcionario do vendedor
}

You’re probably wondering why I didn’t inherit between Salesman/Manager and Employee. In general, for database mapping, This really gets in the way of.

We now come to your questions, based on my suggested mapping.

Recording the sale in the database, what would be the object that would be saved that executed the sale? Employee, Manager or Seller?

Functionary

If you are an employee, at the time of displaying the sale afterwards, and highlight whether the seller was the manager or the seller what to do if Manager has different attributes of Seller and there is no table in the database called Employee with the attributes of Manager and Salesman together?

Go to my suggestion for this case. Identify before opening the screen if the sale was made by the Manager or Seller, making a simple query in the database by the idFunctioning of the Sale in the tables of Seller and Manager. Having this information, you can create the logic to display the information of Seller or Manager on the screen. And at another point of this screen, always display the common information of Manager and Seller, which are the information of the Employee table.

2

It is generally possible to know through the ID, for example manager and seller are both employees, so if there is an employee table that holds the record of all employees of the company, you can only store the ID of the employee who made the sale and with this you can know who made the sale be manager or seller.

  • It seems that all are tending to the same composition! Although run the risk of miscalculation of the employee id when recording in the table manager which the employee (superclass) it but even seems more professional!

  • In this case we will have inheritance in the code and composition in the database!

2

There are three classic options (and not just two)

See the article Types of Inheritance in Hibernate https://www.devmedia.com.br/tipos-de-heranca-no-hibernate/28641 which details the three options. The article also clarifies how the code that performs the mapping between OO and relational can be implemented with the support of Hibernate.

The domain of this problem is known to impedance Ismatch (details wikipedia).

1

You need to understand the difference between variável de referência and objeto de referência.

You see, you declared an object like this Funcionário f = new Vendedor();

What this means for the Java ?

We have the reference variable f which is a Funcionário, and a objeto de referência which is a Vendedor. That means you own one Vendedor in memory, but a variable Funcionário pointing to him.

In practice, what does that mean ?

This means that you have a Seller object that is authorized to use only the inherited/superscript methods of the class Funcionário. Due to the inheritance, we can state that Gerente IS-A Funcionário and Vendedor IS-A Funcionário, but not the other way around.

If you want to check whether the employee is a Manager or a Seller, apply the verification objeto instanceof Vendedor or objeto instanceof Gerente.

Considerations

Given the mapping you presented, I believe the class Funcionário will not be represented in the database, so you will save a Gerente or a Vendedor, for Funcionário it’s just a class abstracting common information between Seller and Manager, can be reviewed later and transformed into a abstract class or an interface, depending on your objectives.

Browser other questions tagged

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