Несколько дочерних классов разных родителей с одинаковой реализацией считаются дублированием кода? ⇐ JAVA
Несколько дочерних классов разных родителей с одинаковой реализацией считаются дублированием кода?
To give a bit of background, we get multiple types of POJO objects holding data of different products. We do not have an abstraction layer which converts those POJOs into one single object.
We are supposed to generate a sort-of common XML out of multiple types of objects. My approach to populate that the XML object by populating it one tag at a time. That one tag is a complex tag with its internal tags changing depending upon the type of data we are sending.
Example, for one product type "S", tag could be
S Vi VSX-1022 and for Product type O, tag could be
O Vi PLL111 Utility And to do that, I have created multiple abstract classes for each such tag. Let's say one such tag is "DSC" as defined in above example. So my abstract class inheritance setup looks something like below.
Current hierarchy
DSC is the super abstract parent which holds all abstract methods. DSC-S and DSC-O are subclasses of DSC super parent which holds some default implementation of some of the methods as they define the type of possible DSC tags. Example DSC-O defines that the abstract class is for representing O product type of DSC tag. And as such, holds a default implementation for the name Tag as "O". (i.e. something like getName(){ return "O" })
Now the leaf nodes, Vi and Ve are the POJOs that I get in my system and they implement this product level abstract class so that they only have to provide the data that is to be extracted from inside them (as each POJO is different), and don't have to provide implementation for something that is same across both Vi and Ve for same product type.
This example is pretty simple, but the actual thing I have to work with has quite a fair bit of complexity on XML tag level.
So what I end up with at some places, is that across multiple products, example O and S, the implementation for "Vi" POJO ends up asking the same data from concrete class which can be extracted in same way. The rest of the data is defaulted in the parent abstract classes (which is different across DSC-S and DSC-O, it's just leaf node only needs that same data).
So that particular extraction I have moved into third class, say ViExtractor and VeExtractor. The Vi implementation of DSC-O calls the ViExtractor.getIdentity for its identity abstract method implementation, and same being the call in DSC-S implementation of Vi.
Here is some code to help picture the current setup
public abstract class DSC { public abstract getName(); public abstract getType(); public abstract getIdentity(); public DSC build(){ dscBuilder.setName(getName()); dscBuilder.setType(getType()); dscBuilder.setIdentity(getIdentity()); } } public abstract class DSC-O extends DSC { @Override public String getName(){ return "O" } } public abstract class DSC-S extends DSC { @Override public String getName(){ return "O" } protected String getSubcategory(){ return "Utility"; } @Override public DSC build(){ dscBuilder.setName(getName()); dscBuilder.setType(getType()); dscBuilder.setIdentity(getIdentity()); dscBuilder.setSubCategory(getSubcategory()); } } public class ViDscOImplementation extends DSC-O { ViExtractor viExtractor; @Override public String getIdentity(Vi vi){ viExtractor.getIdentity(vi); } @Override public String getType(){ return "Vi" } } public class ViDscSImplementation extends DSC-S { ViExtractor viExtractor; @Override public String getIdentity(Vi vi){ viExtractor.getIdentity(vi); } @Override public String getType(){ return "Vi" } } Naturally, there is implementation of VeDSCO and VeDSCS as well which also are same between each other but different from Vi implementation, but I've avoided pasting similar thing again.
As there is no business logic here, would you consider ViDscOImplementation and ViDscSImplementation duplicated? The actual business logic of extraction and post processing is written in ViExtractor, only the function call is being made to there.
Note, DSC-O and DSC-S are just two possible types I have shown here, there are many types, and possibly the implementation could be same for quite a few tags. I don't particularly think it's duplicated, even though it may look that way, because the actual difference is in the parent and I need that difference.
I could probably write some more generic classes, name them adapter and use those adapter instances in DSC super parent to fill in these getIdentity stuff, but it will quickly convolute the entire codebase, as we have a ton of tags and a ton of products. If I do this, and even if it works fine for DSC-O and DSC-S, tomorrow if there is commonality between say DSC-X and DSC-Y but not common with DSC-O and DSC-S, I have to write adapter for those two as well in sub-parent class, there would be no end to it.
The current approach I feel is what keeps it manageable at least into smaller concise classes having specific role, while providing ease of modification in case tags change for any product in future. And keeping business logic of extracting data in extractor classes to allow for easy post processing of data across all tags if required, as long as it is not considered duplication of course.
I tried using interfaces with default implementation instead of abstract classes to be able to use multiple inheritance, but was rejected in code review as default interfaces were not designed for exploiting multiple inheritance.
Источник: https://stackoverflow.com/questions/780 ... considered
To give a bit of background, we get multiple types of POJO objects holding data of different products. We do not have an abstraction layer which converts those POJOs into one single object.
We are supposed to generate a sort-of common XML out of multiple types of objects. My approach to populate that the XML object by populating it one tag at a time. That one tag is a complex tag with its internal tags changing depending upon the type of data we are sending.
Example, for one product type "S", tag could be
S Vi VSX-1022 and for Product type O, tag could be
O Vi PLL111 Utility And to do that, I have created multiple abstract classes for each such tag. Let's say one such tag is "DSC" as defined in above example. So my abstract class inheritance setup looks something like below.
Current hierarchy
DSC is the super abstract parent which holds all abstract methods. DSC-S and DSC-O are subclasses of DSC super parent which holds some default implementation of some of the methods as they define the type of possible DSC tags. Example DSC-O defines that the abstract class is for representing O product type of DSC tag. And as such, holds a default implementation for the name Tag as "O". (i.e. something like getName(){ return "O" })
Now the leaf nodes, Vi and Ve are the POJOs that I get in my system and they implement this product level abstract class so that they only have to provide the data that is to be extracted from inside them (as each POJO is different), and don't have to provide implementation for something that is same across both Vi and Ve for same product type.
This example is pretty simple, but the actual thing I have to work with has quite a fair bit of complexity on XML tag level.
So what I end up with at some places, is that across multiple products, example O and S, the implementation for "Vi" POJO ends up asking the same data from concrete class which can be extracted in same way. The rest of the data is defaulted in the parent abstract classes (which is different across DSC-S and DSC-O, it's just leaf node only needs that same data).
So that particular extraction I have moved into third class, say ViExtractor and VeExtractor. The Vi implementation of DSC-O calls the ViExtractor.getIdentity for its identity abstract method implementation, and same being the call in DSC-S implementation of Vi.
Here is some code to help picture the current setup
public abstract class DSC { public abstract getName(); public abstract getType(); public abstract getIdentity(); public DSC build(){ dscBuilder.setName(getName()); dscBuilder.setType(getType()); dscBuilder.setIdentity(getIdentity()); } } public abstract class DSC-O extends DSC { @Override public String getName(){ return "O" } } public abstract class DSC-S extends DSC { @Override public String getName(){ return "O" } protected String getSubcategory(){ return "Utility"; } @Override public DSC build(){ dscBuilder.setName(getName()); dscBuilder.setType(getType()); dscBuilder.setIdentity(getIdentity()); dscBuilder.setSubCategory(getSubcategory()); } } public class ViDscOImplementation extends DSC-O { ViExtractor viExtractor; @Override public String getIdentity(Vi vi){ viExtractor.getIdentity(vi); } @Override public String getType(){ return "Vi" } } public class ViDscSImplementation extends DSC-S { ViExtractor viExtractor; @Override public String getIdentity(Vi vi){ viExtractor.getIdentity(vi); } @Override public String getType(){ return "Vi" } } Naturally, there is implementation of VeDSCO and VeDSCS as well which also are same between each other but different from Vi implementation, but I've avoided pasting similar thing again.
As there is no business logic here, would you consider ViDscOImplementation and ViDscSImplementation duplicated? The actual business logic of extraction and post processing is written in ViExtractor, only the function call is being made to there.
Note, DSC-O and DSC-S are just two possible types I have shown here, there are many types, and possibly the implementation could be same for quite a few tags. I don't particularly think it's duplicated, even though it may look that way, because the actual difference is in the parent and I need that difference.
I could probably write some more generic classes, name them adapter and use those adapter instances in DSC super parent to fill in these getIdentity stuff, but it will quickly convolute the entire codebase, as we have a ton of tags and a ton of products. If I do this, and even if it works fine for DSC-O and DSC-S, tomorrow if there is commonality between say DSC-X and DSC-Y but not common with DSC-O and DSC-S, I have to write adapter for those two as well in sub-parent class, there would be no end to it.
The current approach I feel is what keeps it manageable at least into smaller concise classes having specific role, while providing ease of modification in case tags change for any product in future. And keeping business logic of extracting data in extractor classes to allow for easy post processing of data across all tags if required, as long as it is not considered duplication of course.
I tried using interfaces with default implementation instead of abstract classes to be able to use multiple inheritance, but was rejected in code review as default interfaces were not designed for exploiting multiple inheritance.
Источник: https://stackoverflow.com/questions/780 ... considered
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение