-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add simulator for NXT #14
Conversation
Load store
Remove timeout from ICommunicator#write and ICommunicator#read
This PR enables us to check that the code base sent as a PR can be compiled correctly $ gradlew check works properly (and this means tests are green) Additionally, I changed the settings of repositories (drive/drivecommand). This makes following changes: when the test fails, merge button will be disabled. when owners (PILE members) push some code to develop or master, the patch will be merged into the branch after testing. If the test fails, merge process will be canceled. (I've not checked it yet, though...) Issue #8
- Add the build status for `develop` - Fix a typo
This commit adds a feature of simulating NXT robots. Users of the simulator can use NxtMachineSimulator by instantiating that class. The simulator class allows users to create *simulatable* version of sensors/motors by the same way as normal NxtMachine.
According to #12, I added a simulator feature for NXT robots. TODO: add test cases, general controllers. Please feel free to leave any opinions. |
Added a simple use-case in drive. |
I see. The workaround looks good to keep loose couplings :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These comments are based on my comment below.
#12 (comment)
@@ -0,0 +1,38 @@ | |||
package com.pileproject.drivecommand.machine.device.input.simulation; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel these objects are just for mocking. What do you think about moving to com.pileproject.drivecommand.mock.machine.device.input to clarify which classes are available for testing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I don't know which is better to be honest.
@tiwanari might have opinions on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, at first, let me confirm options. They are;
com.pileproject.drivecommand.machine.device.input.mock
(as followed the naming discussion)com.pileproject.drivecommand.mock.machine.device.input
right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, I agree with @amiq11's idea in the case we use these classes just for testing because users can easily understand where these mocks are placed.
Let's regard the mock
package as a small repository for mocks (It may help some developers who implement a communication for other robots).
If some classes, especially *Controller
s, in this PR are general enough (i.e., it can be used not only for such testing/mocking but also for other purposes), we shouldn't move them into the mock
package.
import com.pileproject.drivecommand.machine.device.port.InputPort; | ||
import com.pileproject.drivecommand.model.ProtocolBase; | ||
|
||
public class SimulatedColorSensor extends ColorSensor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel Mock is more common word for this purpose. How about MockColorSensor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
private int illuminance; | ||
|
||
public SimulatedColorSensor(InputPort port, ProtocolBase protocol) { | ||
super(port, protocol); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is super necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's necessary because the superclass does not have a default constructor and then the subclasses must call one of its superclass's constructors.
Welcome to Java!
private float green; | ||
private float blue; | ||
|
||
private int illuminance; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding m
before each members for keeping the naming convention?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah yeah gotcha gotcha...
@@ -0,0 +1,29 @@ | |||
package com.pileproject.drivecommand.model.com; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about moving this class to com.pileproject.drivecommand.mock.model?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as the first reply
/** | ||
* Null object of {@link ICommunicator}. | ||
*/ | ||
public class NullCommunicator implements ICommunicator { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's rename this to MockCommunicator if you agree with the "mock" prefix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
K.
import com.pileproject.drivecommand.machine.device.port.InputPort; | ||
import com.pileproject.drivecommand.machine.device.port.OutputPort; | ||
|
||
public class NxtMachineSimulator extends NxtMachine { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this class could targets not only NxtMachine but all classes derived from MachineBase.
We can move this class to com.pileproject.drivecommand.mock.model, for example, and can also implement MockMachine inheriting MachineBase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once I thought exactly same thing as you thought.
But users of this library might use only one of the machines in this library and
in that case the corresponding mocking class has to be on the line of inheritance of the machine.
So we'd better to provide mocks for the every machines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my understanding, MachineBase should be the interface exactly for such purpose when we designed this library. User's program should handle MachineBase in their codes except for the factory class (currently it's NxtController, right?).
But users of this library might use only one of the machines in this library
I know there is such case, but this library should assume what I mentioned above. Additionally, I'm wondering if there is benefit when users directly use the derived classes like NxtMachine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your opinion seems right.
One thing which made me confused was that NxtController takes NxtMachine as its constructor argument, which seems to have to be MachineBase.
And now I feel that the controller's name is misleading as it implies general enough to be able to control any nxt machines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and NxtController is not a factory class. now MachineProvider is responsible for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not familiar with the actual codes, but I think NxtController should take NxtMachine because NxtController binds each port, which is Nxt(Input|Output)Port, with each device like motors and sensors.
Also, why is MachineProvider separated with the corresponding controller? In my understanding, the controller class shapes the machine. In other words, User's programs can define the model of his/her machine by implementing the controller class (ex: the machine should have two motors, and two sensors). This means MachineBase itself without controller is useless for the user's code (drive in our case). That's why I thought "(currently it's NxtController, right?).".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then the mock class has to be the sub class of the corresponding concrete class doesn't it?
if not, NxtController cannot take mocking instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and technically machines and controllers are tied up in the provider class. it's just because for the simplicity of the implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay... let me summarize your comments.
How about making a common Mock class
Yeah, it's a reasonable way. But, what use cases do you imagine? I think we should refer some use cases (or a purpose) for each case (a common Mock class / Mock classes derived from *Machine
s).
I feel "Mock classes derived from *Machine
s" is a case that we, drive developers, come up with at first because we have separated apps and these classes will be used in the corresponding apps which require a concrete machine class as an argument for their controllers (these controllers have some naming problems as @Myusak mentioned. please see the next section).
The name, NxtController
Some problems of the name;
- It doesn't mention about the form of NXT but, in drive, the class specifies the form/sensors/motors as @amiq11 mentioned (these controllers specify the forms). So the name is too general for the purpose from a viewpoint Maybe, we should rename it like
NxtCarController
if we introduce it in this library. - It indeed says
this class controls an NXT
. So, the class should take aNxtMachine
or one of its children. This is a case in which we need such mocking classes, not a general mocking class.
In short...
I think this is a very complicated problem and you both are right. It depends on situations.
What we should discuss
- What cases do you suppose with the 2 options? (i.e., what is the purpose of each option?)
- Should we choose one of them? Or can we choose both?
- How much should we do in this library?
- Assuming all cases is impossible
- Are some design changes necessary ? (In particular, as for arguments etc.)
import java.io.IOException; | ||
import java.util.Map; | ||
|
||
public class NxtNullProtocol extends NxtProtocol { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also can be moved to com.pileproject.drivecommand.mock.model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as the first reply
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left some comments. We need more discussions.
@@ -0,0 +1,38 @@ | |||
package com.pileproject.drivecommand.machine.device.input.simulation; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, I agree with @amiq11's idea in the case we use these classes just for testing because users can easily understand where these mocks are placed.
Let's regard the mock
package as a small repository for mocks (It may help some developers who implement a communication for other robots).
If some classes, especially *Controller
s, in this PR are general enough (i.e., it can be used not only for such testing/mocking but also for other purposes), we shouldn't move them into the mock
package.
import com.pileproject.drivecommand.machine.device.port.InputPort; | ||
import com.pileproject.drivecommand.machine.device.port.OutputPort; | ||
|
||
public class NxtMachineSimulator extends NxtMachine { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay... let me summarize your comments.
How about making a common Mock class
Yeah, it's a reasonable way. But, what use cases do you imagine? I think we should refer some use cases (or a purpose) for each case (a common Mock class / Mock classes derived from *Machine
s).
I feel "Mock classes derived from *Machine
s" is a case that we, drive developers, come up with at first because we have separated apps and these classes will be used in the corresponding apps which require a concrete machine class as an argument for their controllers (these controllers have some naming problems as @Myusak mentioned. please see the next section).
The name, NxtController
Some problems of the name;
- It doesn't mention about the form of NXT but, in drive, the class specifies the form/sensors/motors as @amiq11 mentioned (these controllers specify the forms). So the name is too general for the purpose from a viewpoint Maybe, we should rename it like
NxtCarController
if we introduce it in this library. - It indeed says
this class controls an NXT
. So, the class should take aNxtMachine
or one of its children. This is a case in which we need such mocking classes, not a general mocking class.
In short...
I think this is a very complicated problem and you both are right. It depends on situations.
What we should discuss
- What cases do you suppose with the 2 options? (i.e., what is the purpose of each option?)
- Should we choose one of them? Or can we choose both?
- How much should we do in this library?
- Assuming all cases is impossible
- Are some design changes necessary ? (In particular, as for arguments etc.)
847b676
to
1f05cc7
Compare
This commit adds a feature of simulating NXT robots.
Users of the simulator can use NxtMachineSimulator by instantiating that class.
The simulator class allows users to create simulatable version of sensors/motors by the same way
as normal NxtMachine.