Open rafaellehmkuhl opened 3 years ago
I would recommend to make MavlinkEndpoint a builder, where you can configure it directly with:
MavlinkEndpoint.create()
.with_endpoint(EndpointData(Endpoint.TCPout, "0.0.0.0", 5600))
.with_configuration(EndpointMetadata(name, owner, persistent, protected))
# and
MavlinkEndpoint.create()
.with_endpoint(EndpointData(Endpoint.TCPout, "0.0.0.0", 5600))
.new_configuration()
.set_name(name)
.set_protected()
As you can see this makes it simpler and much readable.
MavlinkEndpoint
should inherits ConnectionEndpoint
, who else will ? If there is no reason to have such abstracted class you should make the implementation inside MavlinkEndpoint
and use the others classes as simple structures to abstract the data.CompanionEndpoint
is not a good name, since is not really an endpoint, this may be an EndpointMetadata
, as you can see in my example, since the name matches exactly your description. ConnectionEndpoint
, I was thinking about opening the doors for future implementations of different protocols, which demand different connection arguments, but it will have so many other implications and is definitely too much for now. Let's focus on separating the connection-data/metadata.CompanionEndpoint
is an endpoint since it has connection information (through the MavlinkEndpoint
argument it receives), but the names you propose are also good.
CompanionEndpoint(
EndpointMetadata(name, owner, persistent, protected),
MavlinkEndpoint(connection_type, place, argument)
)
- The problem with that approach is that if metadata needs extra fields it'll start the problem all over again.
- Not all fields are necessary, you can have protected and persistent off my default and only true require name and owner.
persistent
and protected
are already defaulted to false
on #166 If metadata happens to need extra required arguments, there's really nothing we can do besides adding them, right?
Yes, you can use a builder validation.
MavlinkEndpoint.builder()
.with_endpoint(EndpointData(Endpoint.TCPout, "0.0.0.0", 5600))
.new_configuration()
.set_name(name)
.set_protected()
# missing required
.create() # create will check the validation and trow or return an optional/result
What would be the advantage of doing that instead of the below?
CompanionEndpoint(
EndpointMetadata(
name=name,
owner=owner,
new_required=new_required,
persistent=persistent,
protected=protected,
new_optional=new_optional
),
MavlinkEndpoint(
connection_type=connection_type,
place=place,
argument=argument
)
)
The context:
We had a class called
Endpoint
, that receives 3 arguments:connection_type
,place
andargument
. Right now, with the new metadata, this class receives 4 more arguments:name
,owner
,persistent
andprotected
, with the last two having defaultfalse
values.The problem:
Two many arguments to instantiate an endpoint, with some of those arguments being unrelated (some are metadata and some are connection data).
The solution:
Separate the Endpoint class into 3 classes:
The base
ConnectionEndpoint
class would be abstract, and represents what anEndpoint
should do, but not how.MavlinkEndpoint
would inherits fromConnectionEndpoint
and implement it (would have basically all the code that is in Endpoint today).CompanionEndpoint
would be a class that has the companion metadata we want to add (name, owner, persistent and protected) and receives also anConnectionEndpoint
instance.In that way, we better separate the concerns (
ConnectionEndpoint
instance will store connection information whileCompanionEndpoint
instance stores the metadata), we make the calls smaller and more clear and we open the possibility for future implementations of new protocols.