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;
|
import cat.hack3.codingtests.marsrover.api.cartography.Coordinates;
|
||||||
|
|
||||||
public interface LocateableRover {
|
public interface LocateableRover extends Rover{
|
||||||
Coordinates getCurrentCoordinates();
|
Coordinates getCurrentCoordinates();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package cat.hack3.codingtests.marsrover.api;
|
||||||
|
|
||||||
import cat.hack3.codingtests.marsrover.api.cartography.Direction;
|
import cat.hack3.codingtests.marsrover.api.cartography.Direction;
|
||||||
|
|
||||||
public interface RiderRover {
|
public interface RiderRover extends AccelerometeredRover{
|
||||||
void moveTowards(Direction direction);
|
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.Direction;
|
||||||
import cat.hack3.codingtests.marsrover.api.cartography.PlanetMap;
|
import cat.hack3.codingtests.marsrover.api.cartography.PlanetMap;
|
||||||
|
|
||||||
public interface RotableRiderRover extends RotableRover, RiderRover, LocateableRover {
|
public interface RotableRiderRover extends RotableRover, RiderRover, ConsciousRover {
|
||||||
|
|
||||||
interface Provider {
|
interface Provider {
|
||||||
RotableRiderRover provideWith(PlanetMap map, Direction startingDirection);
|
RotableRiderRover provideWith(PlanetMap map, Direction startingDirection);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package cat.hack3.codingtests.marsrover.api;
|
package cat.hack3.codingtests.marsrover.api;
|
||||||
|
|
||||||
public interface RotableRover {
|
public interface RotableRover extends Rover{
|
||||||
enum Rotation {LEFT, RIGHT}
|
enum Rotation {LEFT, RIGHT}
|
||||||
|
|
||||||
void rotateTowards(Rotation rotation);
|
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;
|
package cat.hack3.codingtests.marsrover.api.commands;
|
||||||
|
|
||||||
public interface RoverCommand {
|
public interface RoverCommand {
|
||||||
enum Type {MOVE_FORWARD, MOVE_BACKWARDS, TURN_LEFT, TURN_RIGHT}
|
|
||||||
|
|
||||||
void execute();
|
void execute();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package cat.hack3.codingtests.marsrover.api.commands;
|
package cat.hack3.codingtests.marsrover.api.commands;
|
||||||
|
|
||||||
import cat.hack3.codingtests.marsrover.api.RotableRiderRover;
|
import cat.hack3.codingtests.marsrover.api.Rover;
|
||||||
|
|
||||||
public interface RoverCommandFactory {
|
public interface RoverCommandFactory {
|
||||||
RoverCommand create(RoverCommand.Type type);
|
RoverCommand create(String commandName) throws InvalidCommandNameProvided;
|
||||||
|
|
||||||
interface Provider {
|
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.api.commands.RoverCommandFactory;
|
||||||
import cat.hack3.codingtests.marsrover.commands.RoverCommandFactoryImpl;
|
import cat.hack3.codingtests.marsrover.commands.RotableRiderRoverCommandFactory;
|
||||||
|
|
||||||
module rover.commands {
|
module rover.commands {
|
||||||
requires rover.api;
|
requires rover.api;
|
||||||
|
|
||||||
provides RoverCommandFactory.Provider
|
provides RoverCommandFactory.Provider
|
||||||
with RoverCommandFactoryImpl.Provider;
|
with RotableRiderRoverCommandFactory.Provider;
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package cat.hack3.codingtests.marsrover.test.context;
|
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.RotableRiderRover;
|
||||||
import cat.hack3.codingtests.marsrover.api.cartography.Direction;
|
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{
|
public abstract class GivenMarsRoverDeployedOnMarsMap extends GivenMarsMapSquaredWithInitialCoordinates{
|
||||||
static final Direction STARTING_DIRECTION = SOUTH;
|
static final Direction STARTING_DIRECTION = SOUTH;
|
||||||
|
|
||||||
protected RotableRiderRover rover;
|
protected ConsciousRover rover;
|
||||||
|
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
super.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.RoverCommand;
|
||||||
import cat.hack3.codingtests.marsrover.api.commands.RoverCommandFactory;
|
import cat.hack3.codingtests.marsrover.api.commands.RoverCommandFactory;
|
||||||
|
|
||||||
import static cat.hack3.codingtests.marsrover.api.commands.RoverCommand.Type.*;
|
|
||||||
|
|
||||||
public class GivenRotableAndMoveCommandsOnDeployedRoverWithMap extends GivenMarsRoverDeployedOnMarsMap {
|
public class GivenRotableAndMoveCommandsOnDeployedRoverWithMap extends GivenMarsRoverDeployedOnMarsMap {
|
||||||
|
|
||||||
public static final Class<RoverCommandFactory.Provider> COMMAND_FACTORY_PROVIDER = RoverCommandFactory.Provider.class;
|
public static final Class<RoverCommandFactory.Provider> COMMAND_FACTORY_PROVIDER = RoverCommandFactory.Provider.class;
|
||||||
|
@ -15,12 +13,12 @@ public class GivenRotableAndMoveCommandsOnDeployedRoverWithMap extends GivenMars
|
||||||
|
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
var commandFactory = getImplProviderOf(COMMAND_FACTORY_PROVIDER)
|
RoverCommandFactory commandFactory = getImplProviderOf(COMMAND_FACTORY_PROVIDER)
|
||||||
.provideWith(rover);
|
.provideWith(rover);
|
||||||
|
|
||||||
moveForwardCommand = commandFactory.create(MOVE_FORWARD);
|
moveForwardCommand = commandFactory.create("MOVE_FORWARD");
|
||||||
moveBackwardsCommand = commandFactory.create(MOVE_BACKWARDS);
|
moveBackwardsCommand = commandFactory.create("MOVE_BACKWARDS");
|
||||||
turnLeftCommand = commandFactory.create(TURN_LEFT);
|
turnLeftCommand = commandFactory.create("TURN_LEFT");
|
||||||
turnRightCommand = commandFactory.create(TURN_RIGHT);
|
turnRightCommand = commandFactory.create("TURN_RIGHT");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue