Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I remove an inherited object from a child without altering the parent

(note: names were changed to protect the guilty)

So, let's say I am doing modifications in VisualCruft 8 (long since discontinued by the vendor), and applying those modifications to ERP software from "Company A" (long since bought out by "Company S", who then discontinued the software a few years later due to VisualCruft being discontinued itself).

One of the modifications I frequently need to do is to add, change, or remove fields to a form. This is the bread-and-butter of most ERP software and shows up several times a year. The layout of our ERP package, we'll call it "HotPockets Version 3", divides the forms into "class libraries" that in turn are just buckets to hold the form objects proper; and of course, there are "control" objects embedded inside the "forms".

With each install of HotPockets 3 you get the system version of the form, and a child version in a separate class library that is just a re-class of the parent, so that the forms, controls, business logic, etc. are all present in the child. The intent, as stated by the original ("Company A") vendor, is to allow you to make changes to the child that override the parent, while allowing said vendor to release patches/changes/whatever into the parent. In theory this looks great. In practice, there are issues. Specifically, how does one remove or change a control on a form, when the control itself is defined in the parent, and the parent is not to be changed? The intent is to replace a control with a different control that has different behavior, although in some cases I have also had to remove a control altogether. So, you could also ask this as "How do I remove an inherited object from a child without altering the parent"?

There are some known solutions to this, but I am asking the question because I want to see if there is a better answer than what I will provide. To avoid duplicate answers, I will list the currently known solutions, but keep in mind, I am looking for what is not listed here.

Improper Solution 1

While I am not supposed to modify the parent, I do have access to the parent code. I can simply note all of the properties and methods for the control in question, delete the control from the parent, then go back into the child and re-implement all of the properties and methods. For drastic changes, such as replacing a single text box with a grid of something, this is doable. It is, however, completely "against the rules" and the VAR that provides support for this product kinda frowns on it (note: the VAR is NOT "Company A" or "Company S"). Do keep in mind that not only is the original vendor defunct but the product and the language are defunct as well.

Improper Solution 2

"Hide" the component on the parent form, then (if incorporating a new component) add the new changes to the child. This sounds great in practice, until you realize that all of the old code hooks into the parent, which is now...invisible. Which means renaming the parent's version of the component, and going through all of the "port the properties and methods" listed in Solution 1. In which case...why am I doing this again?

Improper Solution 3

For those instances where I want a control to go away, I can hide the control in the child by setting the visibility property. This does not remove or alter any existing code, and everything continues to function. However, the control and the database field bound to it are now "tied up" and unavailable unless I look at something like Solution 1 or Solution 2, because any attempt to mess with the control will possibly result in side effects during calls, and/or replacing data underneath the control programmatically makes it impossible for the user to observe what is happening. And this only addresses the control visually going away - it does not address replacing it.

Extremely Improper Solution 4

Damn the torpedos, delete the control from the parent, full steam ahead!

Obviously, this is a very bad decision...

You'll note that all of the solutions involve touching the parent, something that I am not supposed to do - which brings us full circle to the question.

Other Solutions Not Available

  • Replace HotPockets Version 3 with something else. This is not in the realm of my decision making.

  • Rewrite whatever I need for HotPockets Version 3 with (insert favorite pet language here). While I would not mind doing this - I do have my own pet languages like most folks - it's not a possibility because VisualCruft pretty much works with just itself. Trust me on this, it's about 10x more effort than it is worth to write an extension in VisualWidget 3.14159 or HeyDoYouSmellCoffee or even ILikeSnakes, figure out some kind of cross-language calling, integrate it, test it, get IT management to sign off on it, get the VAR to also sign off on it, than it is to just stick with the native tools in VisualCruft.

  • Have the VAR do it. Don't take it the wrong way, the VAR does a good job providing ongoing support and has provided lots of useful modifications. But there are cost-factors that play into this, and it's more cost-effective if the changes were made by me, rather than the VAR. This has nothing to do with them at all.

like image 897
Avery Payne Avatar asked Jul 01 '14 23:07

Avery Payne


2 Answers

First let me say that from my point of view it is not so easy to quickly get what your question is.

With each install of HotPockets 3 you get the system version of the form, and a child version in a separate class library that is just a re-class of the parent, so that the forms, controls, business logic, etc. are all present in the child. The intent, as stated by the original ("Company A") vendor, is to allow you to make changes to the child that override the parent, while allowing said vendor to release patches/changes/whatever into the parent. In theory this looks great. In practice, there are issues.

>In theory this looks great.

No it does not! Inheritance is the strongest relationship two entities (aka classes) can have. That is why it has been proposed by Gamma in 1994 and it is widely agreed that:

Favor delegation over inheritance!

Delegation is far more decoupled then inheritance. In your case e.g. you could create a key-value store for your customers custom form fields.

However from your question it is not clear to me if such a change is within your field of responsibility. But this is the source of all the "evil" you are describing.


Further on my impression is within your question you mix up a parent-child-relationship within the class structure at design time and a parent-child-structure of a tree-like class-composition of the objects-structure at run time.

Think of it this way: Your classes are File and Folder, and Folder can contain Files... By this you can create arbitrary tree like structures at runtime. This is called the "Composition Design Pattern". If you are not aware of it you will get lots of information on the net.


Finally within your bounty you are proposing

that this is a limit of the OOP paradigm .

IMHO it is not - it is a serious flaw in the design due to a clear misuse of inheritance.

So back to your question:

How do I remove an inherited object from a child without altering the parent?

  1. At design time or at run time? (You can not alter a inheritance at run time)
  2. Remove the inheritance completely at design time.
like image 76
Martin Meeser Avatar answered Oct 29 '22 16:10

Martin Meeser


The question "How do I remove an inherited member of a child" in and of itself is incorrect. I actually know what you mean in this context. However, your wording for the question is basically asking something impossible. If you are creating a parent-child, is-a, inheritance chain between two types, you are assuming one is a more specialized form of the other. If you ever think that human may someday evolve so much that it would have nothing in common with "animals", you should never inherit "human" from "animals". Let's remember that inheritance is as coupled as it gets between classes.

I think Martin is correct in stating that this is not really a limitation in the OOP paradigm. Surely "Hot Pocket" designers knew what type of modifications their users should be able to do when they used inheritance for the child classes. They definitely wanted to "allow" certain changes and "disallow" certain other changes. For example they wanted you to be able to change the behaviour of a control but not be able to remove it.

Having said that, if you do not agree and believe that adding or removing controls is definitely something "Hot Pocket" designers had in mind, then they should have also provided you with a means of doing just that.

All in all, there are three possible scenarios:

-A "Hot Pocket" designers actually give you a way to achieving this(which obviously wouldn't have led to your question here).

-B "Hot Pocket" designers messed up. They didn't have a clue a user may need to delete a control in a child class.

-C "Hot Pocket" designers knew what they were doing. They don't want you to be able to add or delete a control to the child forms.

In Case A), we already have a solution. Just as the "Hot Pocket" people.

In case B), as it is their fault they can't frown on you having to change the parent because otherwise you have no "good" choice.

In case C), you either submit to the limitation or as in your case, you are forced to change the parent although that is not supported. Of course, that would cause frowns and come with its caveats because you are going against the design.

This is getting longer that I intended, I finish with maybe one more solution that you have not added.

Given the fact that you have no way of "deleting" an inherited member, maybe a better approach than changing the parent would be actually adding a new parent for your special case. If you need to remove a control, in a new copy of the parent make your changes and have the child inherit from the new parent class. By doing this you are actually extending the framework rather than changing it. Maybe this would cause less frowns?

like image 41
Farhad Alizadeh Noori Avatar answered Oct 29 '22 17:10

Farhad Alizadeh Noori