Coding Hygiene & Client-Server Tier in Dynamics 365 Finance & Operations
Question 29 — Tier-aware code, CRUD placement, and the performance hygiene rules every developer should follow.
Interview Question
Model Answer (Short)
Coding hygiene is the set of disciplines that keep X++ code fast, clean and maintainable. A big
part is tier awareness: avoid mixing client and server code, and run almost all
CRUD operations on the server to minimise AOS↔DB round trips. You should never put CRUD in
display or edit methods, never do INSERT/UPDATE inside
modified/validate methods, and never run validations in modified methods. Prefer
set-based operations, specify field lists, use firstOnly,
convert nested selects to joins, cache display methods on grids, and avoid
direct SQL in forms and ttsAbort.
Client-Server Tier Awareness
Where code should run
- Avoid client-server mix when writing classes — it causes costly round trips.
- Almost all CRUD operations should run on the server.
- For InMemory and TempDB tables, decide the tier based on where the table is created.
- Methods with client interaction should not execute on the server; separate code by execution tier if needed.
What NOT to do in specific methods
- Display / Edit methods must not contain CRUD operations.
- INSERT/UPDATE should not happen in modified or validate methods.
- Validations should not happen in modified methods.
- Call
validateXXXbefore an INSERT/UPDATE/DELETE where required.
Core hygiene rules
- Specify a field list for customized X++ SQL; use
firstOnlywhere applicable. - Prefer set-based operations; call the necessary skip methods so they don't fall back to row-based.
- Convert nested selects to joins; use exists / notexists join when only testing for related rows.
- Replace FIND with a select of only the needed fields where appropriate (considering table group / cache).
- Use RecordInsertList when
insert()is overridden and called in a loop. - Avoid direct SQL in forms (it slows form loading); use views/queries instead.
- Use balanced
ttsbegin/ttscommit, avoid multiple TTS blocks, and avoidttsAbort. - Cache display methods shown on grids.
Prerequisites (Rule 5)
- Visual Studio with the Dynamics 365 developer tools.
- A custom model / package for your objects.
- Understanding of method tiers and the table's overridden methods.
Code Example — Validate before write
public boolean createRecord(AbcOrderHeader _header)
{
boolean ret = false;
// Run validation BEFORE the write
if (_header.validateWrite())
{
ttsbegin;
_header.insert();
ttscommit;
ret = true;
}
return ret;
}
Marking a method to run on the server tier
// Server-side method keeps CRUD off the client tier
server static void processOnServer(AbcOrderId _orderId)
{
AbcOrderHeader header;
ttsbegin;
select forUpdate header
where header.OrderId == _orderId;
header.Processed = NoYes::Yes;
header.update();
ttscommit;
}
Cached display method (kept lightweight)
// Lightweight display method — no CRUD, cache it on the grid data source
public display Amount displayLineTotal()
{
return this.Qty * this.Price;
}
Good vs. Poor Hygiene
| Area | Good hygiene | Poor hygiene |
|---|---|---|
| CRUD placement | On the server tier | Mixed client-server / in display methods |
| Data volume | Set-based with skip methods | Row-by-row loops |
| Queries | Field lists, firstOnly, joins | Whole records, nested selects |
| Forms | Views/queries, cached display methods | Direct SQL, uncached display methods |
| Transactions | Balanced tts, no ttsAbort | Multiple/unbalanced tts, ttsAbort |
Points the interviewer wants to hear
- Avoid client-server mix; run CRUD on the server.
- No CRUD in display/edit; no INSERT/UPDATE in modified/validate.
- Always validate before write.
- Use field lists, firstOnly, joins and set-based operations.
- Avoid direct SQL in forms and
ttsAbort; cache grid display methods.
Likely Follow-up Questions
- Why is client-server mixing bad for performance?
- Why should INSERT/UPDATE not appear in modified/validate methods?
- Why avoid direct SQL in forms?
- Why is
ttsAbortdiscouraged?
Key Takeaway
Good coding hygiene means tier-aware code that runs CRUD on the server, keeps
display/validate/modified methods side-effect-free, validates before writing, favours
set-based and field-list queries, and avoids direct SQL in forms and
ttsAbort.