Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best way to handle type indicators in object-oriented design? [duplicate]

We have a business model that requires, say, different types of vehicles to be identified. For example, motorcycle, boat, yacht, farm equipment, snowmobiles, heavy truck, light truck, passenger car, and "Other".

I think there are two ways to handle it: Create a Vehicle class with a few subclasses, say, boat, truck, car and have a single enum indicating the actual type. This would work, allowing you to represent vehicles that share some common features with common subclasses. But it allows you to have mismatched enums with the classes.

I think the traditional way to handle it is to have a separate subclass for each type, which may subclass the vehicle, or a subclass of vehicle. For example, heavy and light truck might subclass truck; boat and yacht might subclass boat; snowmobile might subclass vehicle. The problem is, it doesn't really lend itself to representing the concept of other.

Does anyone have any patterns or best-practices for these sorts of scenarios?

Peter

EDIT: The purpose of the object is to convey information about the vehicle and to be able to display that information in a user-friendly way. For example, pull the data from a database and display it on a screen to be viewed/edited.

This leads to another downside to the traditional OO means that leans away from type indicators for actual types, in that to display the type one would need to perform some sort of instance-of and convert the value to something user-friendly.

(Also, clarified I was talking about a single enum, not an enum per subclass.)

like image 876
Risser Avatar asked Apr 29 '14 14:04

Risser


People also ask

What are the most important activities in object oriented design process?

Object-oriented design is fundamentally a three-step process: identifying the classes, characterizing them, and then defining the associated actions.

How did object-oriented programming systems handle complexity better than procedural process?

Security: Object-oriented programming is more secure than procedural programming, because of the level of abstraction or we can say data hiding property. It limits the access of data to the member functions of the same class. While there is no such data hiding in the procedural programming paradigm.

What are the three main things of object oriented design?

There are three major pillars on which object-oriented programming relies: encapsulation, inheritance, and polymorphism.

Which feature of the object-oriented paradigm which helps code reuse is?

Feature of object oriented paradigm helps code reuse is Inheritance - Objects Design.


3 Answers

I would start with a Vehicle and not add too much abstraction.
I wouldn't use the class hierarchy to describe something you could use a field to describe.

Is the code for these types so different?

For example, say you have a type you didn't think of before. like an aqua-car (which is a car which can travel over water) or a seyway, or a unicycle. You could create a new class for each type or you could have it entirely data driven with fields like

name: aqua-car
type: Exotic Car
travelsOnWater: true
travelsOdLand: true
wheels: 4

I suggest you read You Ain't Gonna Need It Better to add only the abstraction you need, not the abstraction you can imagine.

like image 59
Peter Lawrey Avatar answered Oct 19 '22 06:10

Peter Lawrey


The Real Question

How different do two "things" need to be before they deserve their own class?

The Answer

It depends entirely on how you are going to use the objects.

  • Will you be comparing them based on some property they have (e.g., does it float?)? If so, a single class with a differentiating property makes sense.
  • Are you going to display your objects on an interface? Would it make sense within your application to display Light Trucks and Heavy Trucks in a single table? If they cannot meaningfully exist and be displayed as one data set, then it makes sense to have two classes.

Those are just two examples. The point is, if you create a new class, it should be useful. Java is particularly prone to over-abstraction.


What do I do about Other?

Other sounds like a group of Vehicles that are not Trucks and not Cars. It sounds like you want to catch all other Vehicles and put them in one class. Why not use the Vehicle class? Don't create another class that derives from Vehicle but adds zero functionality. The same usefulness test applies here.

  • Is a Vehicle useful enough to satisfy my needs for all "other" vehicles? If not, I need to create more classes.

I took your advice and created two useful classes. Now, I can't tell them apart and I refuse to use instanceof. What do I do?

No matter how abstracted your classes are, I will always be able to add instances your class to a List<Object> and will then be unable to tell them apart. You cannot bulletproof your design.

Let me put it another way - if you add Eggs and Cars to a List, and you later need to differentiate between Eggs and Cars, then there is a problem with your List, not the Eggs and Cars.

like image 37
Rainbolt Avatar answered Oct 19 '22 06:10

Rainbolt


There is not simple answer for your question. Because its depend on the business logic you will have to perform with that data structure.

I would start with an interface Vehicle that will resolve a Identyficator from to get the description of concrete representant.

interface VehicleIdentyficator {
  String identyficator();
}

interface Vehicle {

  Identyficator getIdentyficator();

}

With this you are not limited to class, enum or other kind of design.

Then i would use class hierarchy to describe the properties of each vehicle.

After that add some logic/behavioural aspects to the code and get a look that my data structures are valid for the task.

At the end of the day the important aspect is to perform some operations.

For example there is no point of creation three classes Truck, LightTruck and HavyTruck.

You could create a class that describe them by task they perform

  • They can transport on ground
  • The Light truck can carry less load but it used to travel in small cities.
  • The Heavy truck is opposite to Light. Have big Range carry more load.

When we compare to this a boat we see that boat is more like light truck the only difference is that it travel on water.

So try to understand the object not be what it is but what it can do. What tasks can be performed by it and what are the limitation. Then with your design will be really close to what you need.

I hope this sentence is correct and i will repeat myself. It seams that you are using those vehicles, not constructing them. So focus on their mission to full fill not on their physical aspects.

But you can do something like this

 enum VechicleType implements VehicleIdentyficator {
   TRUCK("TRUCK"),
   HEAVY_TRUCK("HEAVY_TRUCK")

   private final String indentyficator;

   private VechicleType(String indetyficator) {
     this.indentyficator = identyficator;
   }

   public String identyficator() {
       return indentyficator; 
   }

 }

But then every time you add some new vehicle you must cover all points where such new hard coded type will be used.

like image 2
Damian Leszczyński - Vash Avatar answered Oct 19 '22 07:10

Damian Leszczyński - Vash