# Objects, fields and picklists — the full rules

House rules for this org. Where they differ from generic Salesforce advice, these win.

## Spelling

English spelling for every label and API name, without exception. `Organisation`, `Authorised`, `Cancelled`. Mixed spelling across an org makes fields impossible to find by search.

## Custom objects

| Rule | Detail |
|---|---|
| Uniqueness and case | Names are unique across the org and begin with an uppercase letter |
| API name | The auto-generated one, derived from the label. Never hand-written camel case (`DoNotUseCamelCase`) |
| Acronyms | Avoid them, in both the label and the API name |
| Number | **Singular** — `Problem__c`, not `Problems__c` |
| Label | No underscores. Underscores belong to the API name, which the platform generates |
| Junction objects | Named for the two objects joined, with the **primary parent first** — the one that defines sharing. `Problem_Part__c` |

Every object carries **at least one record type**, even where there is only one variant today; adding the second later is far cheaper than retrofitting the first. Security is granted through permission sets and profiles. Many-to-many relationships go through a junction object rather than a pair of lookups.

## Custom fields

| Rule | Detail |
|---|---|
| API name | Auto-generated from the label |
| Acronyms | Avoid |
| Date | Label and API name both end in `Date` — `Shipped Date` → `Shipped_Date__c` |
| Date/Time | Label ends `Date/Time`, API name ends `Date_Time` — `Shipped Date/Time` → `Shipped_Date_Time__c` |
| Checkbox | Do **not** prefix with `Is`. `Active__c`, not `Is_Active__c` — the field type already states it is a boolean |
| Lookup | Include the target object name where possible — `Primary_Contact__c`, `Parent_Problem__c` |
| Numeric-leading label | API name starts with `x`. A label of `2024 Target` becomes `x2024_Target__c`; the platform cannot start an identifier with a digit |
| Label length | Short. Detail belongs in help text and the description |

### Before creating one

1. Is there a **standard field** that already carries this meaning? Use it.
2. Is there an **existing custom field**? Use it rather than adding a near-duplicate.
3. Only then create a field — and prefer a **picklist** over free text wherever the values are knowable, so the data stays reportable.

### After creating one

- **Add field-level security to the four admin profiles**: System Administrator, System Specialist, System Specialist Lite, System Integration. A new field is invisible until FLS is granted, and an admin who cannot see it cannot support it.
- Fill in the **Description** explaining what the field is for. The schema is the documentation.
- Turn on **History Tracking** only for fields that genuinely warrant it — tracking is not free, and tracking everything means noticing nothing.

## Picklists

**Never paste picklist values from Word or Excel.** Both carry invisible characters — non-breaking spaces, smart quotes, zero-width joiners — that survive the paste and then break every comparison, validation rule and integration mapping that expects the visible string. Retype the values, or paste through a plain-text editor first.

## Worked example

A junction between Problem and Part, where Problem drives sharing:

| Element | Label | API name |
|---|---|---|
| Object | `Problem Part` | `Problem_Part__c` |
| Master-detail to Problem (primary, listed first) | `Problem` | `Problem__c` |
| Master-detail to Part | `Part` | `Part__c` |
| Date the link was made | `Linked Date` | `Linked_Date__c` |
| Whether the link is confirmed | `Confirmed` | `Confirmed__c` |

Note what is *not* there: no `Is_Confirmed__c`, no `ProblemPart__c`, no plural, and no underscore in the object label.
