Say I have a business model called Vehicle
. Vehicle
has many fields but to keep it simple say it looks like:
public class Vehicle {
String ownerName;
String brand;
FuelType fuelType;
}
public enum FuelType{
GAS,ELECTRIC,PETROL
}
Now, this model has its own semantics in the domain. For example, this model is an entity meaning it gets persisted in a "something the GUI should not know about" (database). So there is a VehicleService
that manages things like this. There are also things like VehicleExportService
that exports a business.Vehicle
(s), say to PDF files.
Now, the GUI (which is desktop) needs to show vehicles. If I use this model to show and let user edit vehicles, many parts of my GUI (ToolTipCreators, Controllers, Widgets) depend on this class (has import business.Vehicle
) hence I consider this as "coupling" (please, give me a clarification if its not). Plus, during "store vehicle edits by user" phase or during "export" phase, parts of the application (mostly controllers) must depend on VehicleService
and VehicleExportService
. Changing things in domain, things in GUI must change too. Also, during GUI tests I will have to mock VehicleService
. If one day I delete VehicleService
, GUI tests will break.
So, in order to decouple and increase modularity, I introduce a gui.VehicleModel
(MVC/MVP/Whatever). This allows me to add a save()
or export()
method. It is also an interface to let me test, without creating business.Vehicle
objects during GUI testing or need to mock VehicleService
.
Now, these 2 meet at gui.adapt.VehicleAdapter
class that implements gui.VehicleModel
. It takes in constructor a business.Vehicle
, a VehicleService
and a VehicleExport
service and long story short, it just delegates the calls to business. For example, it looks like this:
public class VehicleAdapter implements VehicleModel {
public VehicleAdapter(Vehicle origin, VehicleService service, VehicleExportService exportService) {
...
}
//getters and setters for all Vehicle fields
@Override
public void save() {
service.save(origin);
}
@Override
public void export() {
exportService.export(origin);
}
}
Now, the whole GUI works with VehicleModel. Changing business.Vehicle
or say business splits VehicleService to VehicleSaveService
and VehicleDeleteService
will only require to change the adapter.
After all that are done, I think decoupling is achieved. I use this approach for other models (say VehicleOwner, or Brand or whatever) too. I have a gui.adapt
package that is the only package accessing business
package. However, what I find suspicious is the duplication between the 2 models. Between the MVC model (for GUI) and the business model. Vehicle has 30 fields (give or take). So, the interface has 30 getters and setters. The business model has 30 getters and setters and the MVC model has 30 getters and setters as well.
Am I overengineering? Should I use business models in the GUI? Do I have wrong impression of what "decoupling" means? Do I have wrong impression of what DRY stands for?