In Salesforce il modello dati si legge come un foglio di calcolo tradotto: la tabella diventa l’oggetto, le colonne i campi, le righe i record. Trailhead separa gli standard objects, «objects that are included with Salesforce» — Account, Contact, Lead, Opportunity — dai custom objects, «objects that you create to store information that’s specific to your company or industry». Il suffisso __c nell’API name è «an easy way to tell that a particular field is a custom field».
Che cosa c’è dentro un oggetto
Su un oggetto convivono famiglie di campi diverse: i system field di sola lettura come CreatedDate e LastModifiedDate, il name field — testo oppure Auto Number con un display format del tipo REV-{0000}, scelto alla creazione dell’oggetto — e i campi custom, quelli che «you create on standard or custom objects». Questi ultimi si aggiungono sia agli oggetti standard sia ai tuoi, e sono gli unici che puoi davvero cancellare: un campo standard si toglie dal layout e si nega con la field-level security.
L’altra metà dell’architettura sono i record type: sullo stesso oggetto convivono processi diversi, e il record type decide quale page layout vede un profilo e quale sottoinsieme dei valori di una picklist gli viene offerto. Non crea un oggetto nuovo, non nasconde record ad altri utenti, non sostituisce la sicurezza.
Il modello delle relazioni
Le relazioni sono «a special field type that connects two objects together». Le due principali sono lookup e master-detail, e la scelta si decide su una domanda: il figlio ha senso da solo?
| Lookup | Master-detail | |
|---|---|---|
| Dipendenza | «objects in lookup relationships usually work as stand-alone objects» | «the detail object doesn’t work as a stand-alone» |
| Cancellazione del padre | il figlio sopravvive | «all its related detail records are deleted as well» |
| Visibilità dei dati | indipendente | il master «controls certain behaviors of the detail object, like who can view the detail’s data» |
| Roll-up summary sul padre | no | sì |
| Dove si crea il campo | sull’oggetto che «guarda» l’altro | «always on the detail object» |
Un caso da riconoscere subito: un oggetto custom Review che raccoglie i feedback dei colloqui non ha significato fuori dalla Position a cui si riferisce, e quando la Position sparisce devono sparire anche le review. Non è una validation rule e non è un flow: è un campo Master-Detail Relationship creato su Review e puntato a Position — la cascata è un comportamento della relazione, non automazione da costruire. C’è poi la hierarchical relationship, «a special type of lookup relationship» disponibile solo sull’oggetto User.
Molti-a-molti: il junction object
Quando due oggetti si riferiscono l’uno all’altro in entrambe le direzioni — ogni Position è pubblicizzata su molti siti, ogni sito pubblicizza molte Position — nessuna delle due relazioni base basta. «A junction object is a custom object with two master-detail relationships, and it is the key to making a many-to-many relationship». Si crea un terzo oggetto custom (nell’esempio Trailhead Job Posting) e su di esso due campi Master-Detail Relationship, uno verso Position e uno verso Job Posting Site: «through those many-to-one relationships, you create a many-to-many relationship». Aprire una Position e vedere ogni sito su cui è pubblicata è la related list che ne nasce, resa leggibile portando sul layout i campi dell’altro padre.
Roll-up summary: è la relazione a decidere
Un roll-up summary «calculates values from a set of related records» e si definisce «on the object that is on the master side of a master-detail relationship»; i figli «must be directly related to the master through a master-detail relationship». I tipi sono COUNT, SUM, MIN, MAX: SUM aggrega number, currency e percent, MIN e MAX anche date e date/time.
Da qui la trappola più frequente: un oggetto custom Payment legato ad Account da un campo lookup non può alimentare un roll-up summary su Account. O si converte la relazione in master-detail — possibile solo se ogni record figlio ha il campo relazione valorizzato — o si rinuncia al roll-up.
Schema Builder: che cosa cambia davvero
Schema Builder «lets you visualize and edit your data model». Trascinare un oggetto sul canvas è solo disegno: «this doesn’t change your objects or relationships». Creare si fa dalla scheda Elements, dove «you can create relationship fields, formula fields, and normal fields»: si trascina un elemento Object, oppure «choose a field type and drag it onto the object». Due conseguenze: il campo nasce sull’oggetto su cui lo lasci cadere — trascinare Lookup Relationship su Review crea il lookup su Review, che diventa il figlio — e nulla esiste finché non compili i dettagli e premi Save.
Picklist, dipendenze e cancellazioni
Le picklist sono standard, custom o custom multi-select, restricted («Restrict picklist to the values defined in the value set») o unrestricted, con valori che entrano «via the API, automation, or other apps». Sui valori l’esame gioca su tre verbi. Deactivate toglie il valore dalle scelte future ma «existing records containing a value when you set it to Inactive continue to contain the value». Replace lo sostituisce, e con un valore vuoto «existing records will not display the value anymore». Delete lo rimuove con un job in background.
Una picklist dipendente filtra i valori «based on a selection from another picklist or a checkbox (the controlling value)»: il controllante è una picklist o una checkbox, mai un multi-select, che può solo fare il dipendente. Si configura in Setup → Object Manager → Fields & Relationships → Field Dependencies.
I global value set servono quando lo stesso elenco deve vivere su più campi e più oggetti: «global value sets let you share the same picklist values with more than one picklist field», e «the changes apply to all picklist fields that use the global value set». Alla lettera: «Global value sets are always restricted. You can’t convert them to unrestricted».
Cancellare un campo non è un click: non si può cancellare «without removing field dependencies», e la buona pratica è «deprecate, remove from user permissions, set a period of time to wait for feedback, and then delete». Il pulsante Where is this used? elenca i riferimenti; bloccano quelli che userebbero il campo a runtime — formula field (comprese le cross-object), validation rule, roll-up summary che lo aggrega, flow e Apex, field dependency in cui è controllante o dipendente. Una presenza in page layout o in un report non pesa allo stesso modo.
Quando il problema non è il campo ma che cosa ci finisce dentro, lo strumento è il lookup filter, nella sezione Lookup Filter del campo di relazione: «lookup filters limit the records available in the lookup». Per impedire che su un Case si scelga il contatto di un altro account il criterio confronta Contact Name: Account ID equals Case: Account ID con Filter Type Required, così che «users can only select contacts related to the account selected in the case Account Name field».
Trappole tipiche d’esame
- «Molti-a-molti» non è una relazione, è un oggetto. La risposta giusta contiene sempre un terzo oggetto custom con due master-detail. E se il requisito dice «il figlio non ha senso da solo» e «cancellando il padre spariscono i figli», la risposta è master-detail, non un flow.
- Roll-up summary e lookup non stanno insieme. Il campo si crea sul lato master di una master-detail. Prima si converte la relazione — e si può solo se tutti i figli hanno il padre valorizzato — poi si somma.
- Deactivate, Replace e Delete non sono sinonimi. «Non più selezionabile ma ancora visibile sui record esistenti» = deactivate. Replace con valore vuoto e Delete tolgono il dato.
- Il campo controllante non può essere un multi-select. Il multi-select può essere solo dipendente: la risposta corretta è «non si può fare», non «si fa così».
- Global value set = sempre restricted. I valori si modificano nel value set, non sul singolo campo, e la modifica si propaga a tutti i campi che lo usano.
- In Schema Builder trascinare non basta. Muovere un oggetto sul canvas non cambia niente; trascinare un elemento relazione apre la creazione del campo sull’oggetto di destinazione, e serve comunque un Save.