We are going to create a Monopoly game in Salesforce. Over the course of several blogs, I will build this game step by step and, using this example, teach you the necessary skills and best practices.
How to get started on you design?
When designing an app, I first visualize the user process from start to finish to identify the technical requirements.
In this case, we actually will have a look inside the box of a real Monopoly game, look at its contents, and read through the rules.
The first thing you find in the box is the game board. From here, we can already work out many of the details we need.
- There are 40 positions on the board that players can move to.
- The order of the posiitions on the board is important
- All positions have a name
- Some positions can be purchased by players and have a purchase price.
- When you buy a street, station, or utility, you receive a card that represents this property.
- Streets, utilities, and stations belong to groups.
- The group affects the rent you can charge and determines whether you can buy houses and hotels.
- On some posiitions, you have to pay when you land on them.
- Sometimes you pay the bank, and other times you pay another player.
- On certain positions (Chance, Community Chest, Go, Taxes, Free Parking, Go to Jail), a special game rule applies when a player lands on them.
First draft for the datamodel
Based on this analysis of just the game board, I can already work out a significant portion of the data model.
- The board itself in one object.
- Each position on the board should be a child record of the board.
- A space can be linked to a tradable asset (street, station, utility).
- That tradable asset can have a player as its owner, has a purchase price, a mortgage value, and a rent price list.
- The price list entries must include the criteria specifying when each price list rule applies and the corresponding price to be used.
- The tradable asset itself must track the properties that determine the rent price, such as the number of houses.
- A space can be linked to a rule (or a set of rules, such as the stack of Chance cards).
- The players also need a record to track their possessions and position on the game board.
To make the data model flexible and scalable, I only use master-detail relationships where absolutely necessary and leverage many-to-many relationships through junction objects.
Read more on types of object relationships
Although we won't focus on it for now, I want to ensure the data model accounts for the possibility of having multiple games running in parallel and perhaps even allowing other games than Monopoly to partially reuse the same objects.
With the ideas above in hand, I am going to sketch out a data model. I like to use Draw.io for creating these sketches, focusing primarily on the relationships. It would look something like this:
The fork-like shapes at the end of the lines tell which object in the relationship is the child record.
The Position Rule is the only junction object in this model. This is how you create a many-to-many relationship.
This allows the same Rule to be linked to multiple Positions. This makes sense because there is more than one Chance space and more than one Community Chest space, yet both share only one deck of cards.
And the same Position can have multiple Rules associated with it, which is also what we want to achieve since Community Chest and Chance are decks of cards rather than a single, fixed rule that applies every time you land on such a postion.
For the object and field names, I work in English. This approach has two advantages: it’s more convenient for my non-Dutch-speaking colleagues, and what’s been built can easily be deployed to other clients in the future where Dutch might not be the primary language.
Creating the Datamodel in Salesforce
In Schema Builder, you can quickly build and effectively visualize this data model. You can find Schema Builder under Setup > Object Manager > Schema Builder
To create a new object, open the Elements tab and drag an object onto the canvas.
Fill out the following screen
Consonant or Vowel Sound?
When your Salesforce Org's base language is set to English, when creating an object Salesforce will ask whether the object name starts with a consonant or a vowel sound. This lets Salesforce decide when to use 'a' or 'an'. If the base language is Dutch, this becomes a whole different question, namely if the word is masculin/feminin, where the definite article 'de' is used or neuter where 'het' is used.
Unfortunately you can't have both.
As said before I prefer the base language to be English and translate to Dutch using the translation tools provided.
Creating fields on an object is done by dragging them onto the object that is on the canvas.
Keep in mind that you still need to set up object tabs, page layouts, and field-level security separately after creating the objects and fields. Since this approach groups the different types of tasks together, I find it more efficient than going through all those steps for each field individually.
I prefer to fine-tune page layouts later, and I prefer to assign permissions through a permission set rather than a profile. Translating object and field labels, help texts, and picklist values is also a separate step on its own.
The data model we are creating now serves as the foundation, but as the design process progresses, we may discover that additional fields or relationships are needed.
In the table below, you will find the fields that I have currently created on the 8 objects.
Object | Field Name | Field Type |
Board__c | External_ID__c | Text, 40 characters, External Id, Unique |
Position__c | Board__c | Lookup to Board__c object, required |
Index__c | Number, 18 digits, 0 decimals | |
Asset__c | Lookup to Asset__c object, not required | |
External_ID__c | Text, 40 characters, External Id, Unique | |
Asset_Group__c | External_ID__c | Text, 40 characters, External Id, Unique |
Asset__c | External_ID__c | Text, 40 characters, External Id, Unique |
Asset_Group__c | Lookup to Asset_Group__c object, not required | |
Owned_by__c | Lookup to Player__c object, not required | |
Purchase_Price__c | Currency, 6 digits, 0 decimals | |
Base_Rent_Price__c | Currency, 6 digits, 0 decimals | |
Asset_Rent_Rule__c | External_ID__c | Text, 40 characters, External Id, Unique |
Asset__c | Master-Detail to Asset__c object, (always required) | |
Number_of_Assets_in_Group_owned__c | Number, 1 digit, 0 decimals | |
Buildings__c | Picklist, options: none/1 house/2 houses/3 houses/4 houses/hotel | |
Rent_Price__c | Currency, 6 digits, 0 decimals | |
Player__c | External_ID__c | Text, 40 characters, External Id, Unique |
Position__c | Lookup to Position__c object, not required | |
Cash_Balance__c | Currency, 18 digits, 0 decimals | |
Rule__c | External_ID__c | Text, 40 characters, External Id, Unique |
Description__c | Text, 255 characters | |
Action__c | Picklist, options: Receive Money/Pay Money/Move number of steps/Move to Position | |
Destination__c | Lookup to Position__c object, not required | |
Allowed_to_travel_via_Start__c | Checkbox | |
Amount__c | Currency, 6 digits, 0 decimals | |
Number_of_Positions_Forward__c | Number, 2 digits, 0 decimals | |
Financial_Transaction_Party__c | Lookup to Player__c object, not required | |
Position_Rule__c | Position__c | Master-Detail to Position__c object, (always required) |
Rule__c | Master-Detail to Rule__c object, (always required) | |
Index__c | Number, 3 digits, 0 decimals |
Why the External ID's
External IDs are a useful way to establish relationships with parent records when importing data, without having to use the 18-character-long and not-so-easy-to-remember Salesforce record IDs of those Parent Records.
Next Steps
In several upcoming parts of this series, we will further develop our Monopoly app. Along the way, we will focus on topics such as:
- How does a player move around the board?
- What needs to happen when the player arrives at a new Position?
- How do we determine which rent needs to be paid?
- How do you get sent to jail, and how do you get out?
- How do we provide all players with real-time insight into everything happening during other players' turns?
On thursday 30 january you can read part 2 in which we will build a custom app and Lightning Pages.