Mars Rover – Modeling Concepts
Tags: learningthroughexample, csharp, fsharp, functional
Published: 2020-07-06 01:10:58

---
title: Mars Rover – Modeling Concepts
published: true
date: 2020-05-19 13:30:46 UTC
tags: LearningThroughExample,Csharp,Fsharp,FunctionalProgramming
canonical_url: https://blog.thesoftwarementor.com/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](https://fsharpforfunandprofit.com/posts/designing-with-types-making-illegal-states-unrepresentable/) in my code.

I first came across this term while reading [Scott Wlashcin](https://twitter.com/ScottWlaschin)‘s work on the terrific [F# for Fun and Profit](https://fsharpforfunandprofit.com/) 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.

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=finiteValues.cs %}

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=finiteValues.fs %}

### 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).

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=infiniteValues.cs %}

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=infiniteValues.fs %}

### 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 _has _a StreetName, it _has _a State.
> 
> An Address consists of a HouseNumber _and_ a StreeName _and_ a State

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=composition.cs %}

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=composition.fs %}


## 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

[![Domain model for Mars Rover](https://i0.wp.com/blog.thesoftwarementor.com/wp-content/uploads/2020/05/simple-domain-model-relationships.png?resize=341%2C301)](https://i0.wp.com/blog.thesoftwarementor.com/wp-content/uploads/2020/05/simple-domain-model-relationships.png)<figcaption id="caption-attachment-2019">Domain model relationships where Rover has a Location and an Orientation. Orientation is a Direction and Command is not related to anything.</figcaption>

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:

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=direction.cs %}

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=direction.fs %}
### 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:

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=command.cs %}

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=command.fs %}

### 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](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Two_dimensions) 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

[![Domain Model Relationships](https://i0.wp.com/blog.thesoftwarementor.com/wp-content/uploads/2020/05/domain-model-relationships-1.png?resize=406%2C427)](https://i0.wp.com/blog.thesoftwarementor.com/wp-content/uploads/2020/05/domain-model-relationships-1.png)<figcaption id="caption-attachment-2017">Domain model relationships where Rover has a Location and an Orientation. Location is a Coordinate where Coordinate has an X and Y value. Orientation is a Direction and Command is not related to anything.</figcaption>

 

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.

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=coordinate.cs %}

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=coordinate.fs %}

### 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.

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=rover.cs %}

{% gist https://gist.github.com/cameronpresley/45dfdcb1bf4edf1d61539adb8a8170bf file=rover.fs %}

## 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](https://fsharpforfunandprofit.com/posts/designing-with-types-making-illegal-states-unrepresentable/) by Scott Wlaschin
- [Domain Model](https://martinfowler.com/eaaCatalog/domainModel.html) by Martin Fowler