Fighting the 'god' Class
I have two programmatic interfaces for the FT-991A's CAT. There is no substantial complexity to
the commands although some are overload. Rather than be a 'god' object the implementation acted
as a container The container has public properties which act as subcontainers for related commands.
Doing so eliminated the 'god' class but usability issues resulted.
Programmatically no command is published by more than one container. This was to respect the
single responsibility principle. Deciding what went where was a chore because some commands
could have been in multiple containers. In turn when trying to use the programmatic interface
became a game of which subcontainer is the command in.
A second version was written with a 'god' class. The Interface defines 162 public methods and
75 events. The implementation is organized across 7 source files. The internal organization
does not simplify the programmatic interface.
The simplification is sort of an inversion of control. A type can implement multiple interfaces
and the interfaces describe the type's behavior. With a unavoidable 'god' class why not have it
implement multiple 'unrelated' interfaces. This
public class CatImplementation : ICat
can become
public class CatImplementation : IVfo, IRxAudio, ...
Each interface will only expose related functionality
such as VFO commands. A command can be exposed in multiple interfaces without violating the
single responsibility principle as there is only one implementation.
The client view of the 'god' object limited to what the interface exposes
IVfo vfo = new CatImplementation() as IVfo;
vfo.VfoAFrequencyChanged += someEventHandler;
vfo.VfoAFrequency();
The approach above does have issues. Multiple instances of the CatImplementation would be a waste
of resources. Besides that every instance has its own serial port. The approach to use would
be to use dependency injection and declare the 'god' class as a singleton. Then register each
interface with the singleton.
What Goes Where?
The CAT has 90 two-letter commands including the EX command. A number of the commands are overloaded
but not to the extent of the EX command which has 153 overloads. A preliminary attempt has been made
to organize the various interfaces. Currently the interfaces are :
Interface | Command Count |
IVfo | 23 |
IReceiver | 27 |
ITransmitter | 16 |
IMemory | 11 |
ISsb | 11 |
IFm | 11 |
ICw | 11 |
IKeyer | 5 |
IGeneral | 19 |
These interfaces only cover the 89 non-EX commands. There are probably some commands which will
end up being added to other interfaces. Some interfaces may include EX command definitions. None of
this is set in stone.