sacrify type safety to obtain independent deployability when a command is added (now the api module doesn't need to be recompiled+redeployed)
This commit is contained in:
parent
42f1f19926
commit
8860bfcbc0
|
@ -0,0 +1,7 @@
|
|||
package cat.hack3.codingtests.marsrover.api;
|
||||
|
||||
import cat.hack3.codingtests.marsrover.api.cartography.Direction;
|
||||
|
||||
public interface AccelerometeredRover extends Rover{
|
||||
Direction getCurrentDirection();
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package cat.hack3.codingtests.marsrover.api;
|
||||
|
||||
public interface ConsciousRover extends AccelerometeredRover, LocateableRover{
|
||||
}
|
|
@ -2,6 +2,6 @@ package cat.hack3.codingtests.marsrover.api;
|
|||
|
||||
import cat.hack3.codingtests.marsrover.api.cartography.Coordinates;
|
||||
|
||||
public interface LocateableRover {
|
||||
public interface LocateableRover extends Rover{
|
||||
Coordinates getCurrentCoordinates();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package cat.hack3.codingtests.marsrover.api;
|
|||
|
||||
import cat.hack3.codingtests.marsrover.api.cartography.Direction;
|
||||
|
||||
public interface RiderRover {
|
||||
public interface RiderRover extends AccelerometeredRover{
|
||||
void moveTowards(Direction direction);
|
||||
Direction getCurrentDirection();
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package cat.hack3.codingtests.marsrover.api;
|
|||
import cat.hack3.codingtests.marsrover.api.cartography.Direction;
|
||||
import cat.hack3.codingtests.marsrover.api.cartography.PlanetMap;
|
||||
|
||||
public interface RotableRiderRover extends RotableRover, RiderRover, LocateableRover {
|
||||
public interface RotableRiderRover extends RotableRover, RiderRover, ConsciousRover {
|
||||
|
||||
interface Provider {
|
||||
RotableRiderRover provideWith(PlanetMap map, Direction startingDirection);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package cat.hack3.codingtests.marsrover.api;
|
||||
|
||||
public interface RotableRover {
|
||||
public interface RotableRover extends Rover{
|
||||
enum Rotation {LEFT, RIGHT}
|
||||
|
||||
void rotateTowards(Rotation rotation);
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
package cat.hack3.codingtests.marsrover.api;
|
||||
|
||||
public interface Rover {
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package cat.hack3.codingtests.marsrover.api.commands;
|
||||
|
||||
public interface RoverCommand {
|
||||
enum Type {MOVE_FORWARD, MOVE_BACKWARDS, TURN_LEFT, TURN_RIGHT}
|
||||
|
||||
void execute();
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package cat.hack3.codingtests.marsrover.api.commands;
|
||||
|
||||
import cat.hack3.codingtests.marsrover.api.RotableRiderRover;
|
||||
import cat.hack3.codingtests.marsrover.api.Rover;
|
||||
|
||||
public interface RoverCommandFactory {
|
||||
RoverCommand create(RoverCommand.Type type);
|
||||
RoverCommand create(String commandName) throws InvalidCommandNameProvided;
|
||||
|
||||
interface Provider {
|
||||
RoverCommandFactory provideWith(RotableRiderRover rover);
|
||||
RoverCommandFactory provideWith(Rover rover);
|
||||
}
|
||||
|
||||
class InvalidCommandNameProvided extends RuntimeException{}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package cat.hack3.codingtests.marsrover.commands;
|
||||
|
||||
|
||||
import cat.hack3.codingtests.marsrover.api.RotableRiderRover;
|
||||
import cat.hack3.codingtests.marsrover.api.Rover;
|
||||
import cat.hack3.codingtests.marsrover.api.commands.RoverCommand;
|
||||
import cat.hack3.codingtests.marsrover.api.commands.RoverCommandFactory;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class RotableRiderRoverCommandFactory implements RoverCommandFactory {
|
||||
enum RoverCommandType {MOVE_FORWARD, MOVE_BACKWARDS, TURN_LEFT, TURN_RIGHT}
|
||||
private final RotableRiderRover rover;
|
||||
|
||||
public static class Provider implements RoverCommandFactory.Provider {
|
||||
@Override
|
||||
public RoverCommandFactory provideWith(Rover rover) {
|
||||
return new RotableRiderRoverCommandFactory((RotableRiderRover) rover);
|
||||
}
|
||||
}
|
||||
|
||||
private RotableRiderRoverCommandFactory(RotableRiderRover rover) {
|
||||
this.rover = rover;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoverCommand create(String commandName) {
|
||||
var commandType = tryResolvingCommandTypeFrom(commandName)
|
||||
.orElseThrow(InvalidCommandNameProvided::new);
|
||||
return switch (commandType) {
|
||||
case MOVE_FORWARD -> new MoveForwardCommand(rover);
|
||||
case MOVE_BACKWARDS -> new MoveBackwardsCommand(rover);
|
||||
case TURN_LEFT -> new TurnLeftCommand(rover);
|
||||
case TURN_RIGHT -> new TurnRightCommand(rover);
|
||||
};
|
||||
}
|
||||
|
||||
private Optional<RoverCommandType> tryResolvingCommandTypeFrom(String commandName) {
|
||||
try {
|
||||
return Optional.of(RoverCommandType.valueOf(commandName));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package cat.hack3.codingtests.marsrover.commands;
|
||||
|
||||
|
||||
import cat.hack3.codingtests.marsrover.api.RotableRiderRover;
|
||||
import cat.hack3.codingtests.marsrover.api.commands.RoverCommand;
|
||||
import cat.hack3.codingtests.marsrover.api.commands.RoverCommandFactory;
|
||||
|
||||
public class RoverCommandFactoryImpl implements RoverCommandFactory {
|
||||
private final RotableRiderRover rover;
|
||||
|
||||
public static class Provider implements RoverCommandFactory.Provider {
|
||||
@Override
|
||||
public RoverCommandFactory provideWith(RotableRiderRover rover) {
|
||||
return new RoverCommandFactoryImpl(rover);
|
||||
}
|
||||
}
|
||||
|
||||
private RoverCommandFactoryImpl(RotableRiderRover rover) {
|
||||
this.rover = rover;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoverCommand create(RoverCommand.Type type) {
|
||||
return switch (type) {
|
||||
case MOVE_FORWARD -> new MoveForwardCommand(rover);
|
||||
case MOVE_BACKWARDS -> new MoveBackwardsCommand(rover);
|
||||
case TURN_LEFT -> new TurnLeftCommand(rover);
|
||||
case TURN_RIGHT -> new TurnRightCommand(rover);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
import cat.hack3.codingtests.marsrover.api.commands.RoverCommandFactory;
|
||||
import cat.hack3.codingtests.marsrover.commands.RoverCommandFactoryImpl;
|
||||
import cat.hack3.codingtests.marsrover.commands.RotableRiderRoverCommandFactory;
|
||||
|
||||
module rover.commands {
|
||||
requires rover.api;
|
||||
|
||||
provides RoverCommandFactory.Provider
|
||||
with RoverCommandFactoryImpl.Provider;
|
||||
with RotableRiderRoverCommandFactory.Provider;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package cat.hack3.codingtests.marsrover.test.context;
|
||||
|
||||
import cat.hack3.codingtests.marsrover.api.ConsciousRover;
|
||||
import cat.hack3.codingtests.marsrover.api.RotableRiderRover;
|
||||
import cat.hack3.codingtests.marsrover.api.cartography.Direction;
|
||||
|
||||
|
@ -8,7 +9,7 @@ import static cat.hack3.codingtests.marsrover.api.cartography.Direction.SOUTH;
|
|||
public abstract class GivenMarsRoverDeployedOnMarsMap extends GivenMarsMapSquaredWithInitialCoordinates{
|
||||
static final Direction STARTING_DIRECTION = SOUTH;
|
||||
|
||||
protected RotableRiderRover rover;
|
||||
protected ConsciousRover rover;
|
||||
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
|
|
@ -3,8 +3,6 @@ package cat.hack3.codingtests.marsrover.test.context;
|
|||
import cat.hack3.codingtests.marsrover.api.commands.RoverCommand;
|
||||
import cat.hack3.codingtests.marsrover.api.commands.RoverCommandFactory;
|
||||
|
||||
import static cat.hack3.codingtests.marsrover.api.commands.RoverCommand.Type.*;
|
||||
|
||||
public class GivenRotableAndMoveCommandsOnDeployedRoverWithMap extends GivenMarsRoverDeployedOnMarsMap {
|
||||
|
||||
public static final Class<RoverCommandFactory.Provider> COMMAND_FACTORY_PROVIDER = RoverCommandFactory.Provider.class;
|
||||
|
@ -15,12 +13,12 @@ public class GivenRotableAndMoveCommandsOnDeployedRoverWithMap extends GivenMars
|
|||
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
var commandFactory = getImplProviderOf(COMMAND_FACTORY_PROVIDER)
|
||||
RoverCommandFactory commandFactory = getImplProviderOf(COMMAND_FACTORY_PROVIDER)
|
||||
.provideWith(rover);
|
||||
|
||||
moveForwardCommand = commandFactory.create(MOVE_FORWARD);
|
||||
moveBackwardsCommand = commandFactory.create(MOVE_BACKWARDS);
|
||||
turnLeftCommand = commandFactory.create(TURN_LEFT);
|
||||
turnRightCommand = commandFactory.create(TURN_RIGHT);
|
||||
moveForwardCommand = commandFactory.create("MOVE_FORWARD");
|
||||
moveBackwardsCommand = commandFactory.create("MOVE_BACKWARDS");
|
||||
turnLeftCommand = commandFactory.create("TURN_LEFT");
|
||||
turnRightCommand = commandFactory.create("TURN_RIGHT");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue