# Mars Rover - Modeling Concepts

In the last post, we took a look at the problem description for Mars Rover and developed a set of concepts for the problem. From these concepts, we were able to develop common terminology and determine the relationships between the concepts. In this post, I’m going to show how I think about software design in general and how to apply them when modeling in code.

As a note, I’ll be showing code in both C# (for Object-Oriented approaches) and F# (for Functional Programming approaches). Once again, these concepts are fundamentals, but depending on your technology stack, the implementations will vary.

## Design Guidelines

When I’m designing my models, my end goal is to produce software that captures the problem at hand using the same terms that the business uses. By striving for this goal, I can have richer conversations with my stakeholders when I run into interesting interactions of various business rules and can speak to them using the right terminology. In addition to capturing the problem, I will focus on designing my models in such a way that a developer can’t violate a business rule because the code won’t compile. At this point, I would have made illegal states unrepresentable in my code.

I first came across this term while reading Scott Wlashcin‘s work on the terrific F# for Fun and Profit website and it immediately resonated with me. I’ve definitely been bitten before working in a codebase where I wrote some code that compiled but blew up in my face during runtime because the parameter I passed in wasn’t valid for the method I was calling. Wouldn’t it be nice if the compiler told me while I was writing the code that what I was doing wouldn’t work? By thinking a bit more about the models being used and what some of their properties are, we can make this goal achievable.

## Modeling Types

With these goals in mind, when it comes to modeling concepts, I naturally gravitate to types and find that types will fall in one of three categories.

### The Type Has a Finite Number of Values

If the type has a finite number of valid values, then we can remove error conditions by defining the type to only be one of those possible options. For those from an Object-Oriented background, *enums* are a great example of modeling these types as you can explicitly set a label for the different values. For those from a Functional background, *sum types* are a great way to model these choices.

Some examples of such a type include the states in the U.S., the suits for a deck of playing cards, or the months in a year.

### The Type Has an Infinite Number of Values

For other types, however, there are so many possible valid values that it’s impossible to list all of them. For example, if we were looking at valid house numbers for an address, any positive integer would be valid so good luck on defining every positive number as an *enum* or *sum type*.

In these cases, I will leverage built-in primitives to model the concept at first. So in the case of *HouseNumber*, an integer might be a good enough spot to start. However, if I then find myself writing code that can work on integers, but shouldn’t work on *HouseNumbers*, then I might wrap a stronger type around the integer (see below).

### The Type Is a Composition of Other Types

As the saying goes, large programs are built by composing a bunch of smaller programs, and types are no different. As we begin to model more complicated types, it’s natural to start thinking about types being composed of other types. For these types, we’ll leverage either *objects* (if following OO) or *records* (if following FP).

One way you can determine if you’re needing a composite type like this is if you find yourself using the word and or has when describing the type, then it’s a composition. For example:

An Address has a HouseNumber, it

hasa StreetName, ithasa State.An Address consists of a HouseNumber

anda StreetNameanda State

### Modeling Types

Now that we’ve talked about some different modeling techniques, let’s see how we can apply those rules as we start to model Mars Rover. From the previous post, we were able to derive the following concepts and relationships:

- A
*Rover*has a Location and an Orientation *Orientation*is the*Direction*that a Rover is facing*Location*is the coordinates that the*Rover*is located at- A
*Command*is something that a*Rover*receives from the User - A
*Direction*can be North, East, South, or West - A
*Command*can be Move Forward, Move Backward, Turn Left, Turn Right, or Quit

Yielding the following graph

Given the above rules, we can start taking a look at how to model these in code! We’ll first start with the models that don’t have a dependency, and then build up from there

### Modeling Direction

From the above requirements, *Direction* can only be one of four possible values (North, East, South, West). So based on that, it looks like we can leverage the first rule and model *Direction* like so:

### Modeling Command

From the above requirements, *Command* can only be one of five possible values (MoveForward, MoveBackward, TurnLeft, TurnRight, and Quit). Based on that, we can once again leverage the first rule and model *Command* like so:

### Modeling Location

After talking more with our Subject Matter Expert, a *Location* is the *Coordinate* where the Rover is located.

Aha! A new concept!

When we ask additional questions, we find out that a *Coordinate* refers to the Cartesian Coordinate System and for the problem we’re solving, we can assume that a *Coordinate* represents two numbers where the first number represents the location from the x-axis and the second number represents the location from the y-axis.

With this new information, our mental model has changed to be the following

Going into further discussion, we find out that both X and Y will be whole numbers for our emulation and that they can be negative. Based on these properties, it sounds like X and Y can be modeled as integers and therefore fall under the second rule.

Given that a Coordinate has to have both an X and Y value, it sounds like *Coordinate* falls under the third rule and that this concept is a composition of X and Y.

### Modeling Orientation

From the above requirements, it seems like *Orientation* is what we call the *Direction* that the *Rover* is facing. Based on that, this sounds like a property that *Rover* would have.

### Modeling Rover

Now that we have both the *Direction* and *Coordinate* concepts designed, we can start designing *Rover*. From the requirements, it looks like *Rover* is a combination of *Direction* (known as Orientation) and a *Coordinate* (known as a Location). Based on that, *Rover* falls under the third rule and looks like the following.

## Wrapping Up

In this post, we implemented the basic types needed to solve the Mars Rover kata! We first started by taking a look at the concepts identified earlier and thought about the characteristics of the type which helped guide us to build software that both uses the terms of the problem domain and also prevents us from creating errors by making illegal states unrepresentable. In the next post, we’ll start adding functionality to our application.

## Additional Reading

- Designing with types: Making illegal states unrepresentable by Scott Wlaschin
- Domain Model by Martin Fowler