Architecture of the guide
Hover to explore · click to jump to a section
- Section 01: Fundamental Principles: The values that guide every technical decision on the Salesforce platform.
- Section 02: Universal Naming: How to name objects, fields, classes and variables consistently across the Org.
- Section 03: Data Model: Conventions for objects, fields, relationships and API Names that scale with the business.
- Section 04: Flow Standards: When to use Flow vs. Apex, how to name it and what logic to never delegate to a Flow.
- Section 05: Apex Development and TDD: One trigger per object, bulkification, governor limits and real test coverage.
- Section 06: Lightning Web Components: Decoupled components, wire adapters, clean communication and accessibility.
- Section 07: Security and Permissions: FLS, CRUD, sharing rules and the principle of least privilege in every query.
- Section 08: PMD Rules: Mandatory static analysis: rules that block the deploy when they fail.
- Section 09: Versioning and Release: Git flow, environments, change sets and dependency management between sandboxes.
- Section 10: Documentation: What to document, how and when, for human developers and for LLMs.
- Section 11: Checklists and Templates: Verification lists before the deploy and standardized delivery templates.
Introduction
What is this document?
This Salesforce Development Standards Guide is Vantegrate's official normative framework for building solutions on the Salesforce platform. It defines the conventions, patterns and best practices that guarantee consistent, maintainable, high-quality code across every project.
The document sets clear rules for naming, code structure, the data model, automations, security and documentation. Each standard is backed by concrete examples, drawn from a real electronic-invoicing implementation on Salesforce, so it can be understood and applied immediately.
Who is it designed for?
Salesforce developers: both new members of the Vantegrate team and experienced developers will find here the mandatory conventions for writing code that integrates cleanly with the rest of the Vantegrate ecosystem.
Architects and tech leads: it provides a reference framework for code reviews, design decisions and the evaluation of technical quality.
Generative AI tools: this document is optimized to be consumed by AI assistants such as Agentforce, Cursor, Claude and other code-generation tools.
How to use this document
For human developers
- Read sections 1 and 2 in full before writing any code.
- Consult the specific section for the type of component you are building.
- Use the checklists in section 11 before every commit and deploy.
- Refer to Appendix A as a quick naming reference.
For AI tools
- Include this document (or the relevant sections) in the prompt context.
- Explicitly reference the naming conventions from section 2.
- Require generated code to follow the patterns in sections 3-6.
- Validate the output against the PMD rules in section 8.
Document design principles
| Principle | Meaning |
|---|---|
| Explicit over implicit | Each rule includes concrete examples of correct and incorrect usage. No prior knowledge is assumed. |
| Optimized for AI | The conventions use consistent terminology and predictable structures that language models can interpret. |
| Practice-oriented | Every example comes from real cases, in particular the electronic-invoicing domain. |
| Evolving | It is updated as new Salesforce capabilities and industry best practices emerge. |
1Fundamental Principles
1.1 Fundamental Rule: English Only
Principle: all code, comments, names of variables, methods, classes, objects, fields and technical documentation must be in English.
Reason: English is the industry standard. It eases global collaboration, improves documentation and enables integration with analysis tools.
| ✓ Correct | ✗ Incorrect |
|---|---|
| AccountService | ServicioCuentas |
| isHighValueCustomer | esClienteValioso |
| Invoice__c | Factura__c |
| TotalAmount__c | MontoTotal__c |
| // Calculate total revenue | // Calcular ingresos |
1.1.1 Distinction between Label and API Name
It is important to distinguish between Label (the value visible to the user) and API Name (the technical name used in code):
- API Name: ALWAYS in English, using PascalCase. It is the technical identifier used in code, formulas, integrations and automations.
- Label: MAY be in the end user's language. It is what the user sees in the Salesforce interface.
| Type | Label (User) | API Name (Code) |
|---|---|---|
| Field | Billing period | BillingPeriod__c |
| Field | Tax exemption code | TaxExemptionCode__c |
| Field | Is primary | IsPrimary__c |
| Object | Invoice line | InvoiceLine__c |
| Record Type | Invoice - Draft | InvoiceDraft |
1.2 Test-Driven Development (TDD)
The TDD cycle is mandatory for all Apex development:
| Phase | Description |
|---|---|
| 🔴 RED | Write a failing test (define the expected behavior). |
| 🟢 GREEN | Write the minimum code to make the test pass. |
| 🔵 REFACTOR | Improve the code while keeping the tests green. |
Coverage requirements
| Type | Required coverage |
|---|---|
| Minimum global coverage | 75% |
| Recommended coverage | 85%+ |
| Critical classes (Services, Handlers) | 90%+ |
| Assertions | Every test MUST have meaningful assertions. |
1.3 Quality and Performance
Golden rules (mandatory):
- 🚫 NEVER run SOQL inside loops.
- 🚫 NEVER run DML inside loops.
- ✓ ALWAYS use bulk processing (design for 200+ records).
- ✓ ALWAYS check Field Level Security (FLS).
- ✓ ALWAYS check CRUD permissions before DML operations.
- ✓ ALWAYS declare the sharing model (
with sharing/without sharing). - 📋 Mandatory compliance with critical PMD rules.
1.4 Native-First Principle
Always prioritize native Salesforce solutions, in this order:
| Priority | Type of solution | Examples |
|---|---|---|
| 1️⃣ | Third-party solutions | AppExchange or community components (unofficialSF) |
| 2️⃣ | Declarative configuration | Validation Rules, Formula Fields, Roll-up Summaries |
| 3️⃣ | Flows | Record-Triggered, Screen, Scheduled, Platform Event |
| 4️⃣ | Apex | When Flows cannot resolve the requirement |
| 5️⃣ | External integrations | Only when there is no native alternative |
2Universal Naming
This section defines the mandatory naming conventions for every Salesforce development component.
2.1 Case Styles
| Style | Description | Example |
|---|---|---|
| PascalCase | First letter of each word capitalized, NO underscores | InvoiceService |
| camelCase | First word lowercase, the rest capitalized | accountList |
| UPPER_SNAKE_CASE | All uppercase, separated by underscores | MAX_RECORDS |
| kebab-case | All lowercase, separated by hyphens | invoice-form |
2.1.1 Critical Rule: PascalCase with NO internal underscores
The Vantegrate convention requires PascalCase with no internal underscores for the API names of objects and fields.
| ✓ Correct | ✗ Incorrect |
|---|---|
| SecondaryContact__c | Secondary_Contact__c |
| BillingPeriod__c | Billing_Period__c |
| TaxExemptionCode__c | Tax_Exemption_Code__c |
| InvoiceLine__c | Invoice_Line__c |
| PrimaryAccount__c | Primary_Account__c |
2.1.2 Using PascalCase
Apply it to names that represent entities, types or primary structures.
| Component | Example |
|---|---|
| Custom Objects API Name | Invoice__c, InvoiceLine__c |
| Custom Fields API Name | ServiceDate__c, TotalAmount__c |
| Apex Classes | AccountService, InvoiceController |
| Apex Triggers | AccountTrigger, InvoiceTrigger |
| Test Classes | AccountServiceTest, InvoiceControllerTest |
| Flow API Names | Invoice_AfterInsert_SendToAfip |
| Permission Sets | Invoicing_FullAccess, Billing_ReadOnly |
| Validation Rules | Invoice_Amount_Required |
| Record Types (DeveloperName) | InvoiceDraft, InvoicePosted |
2.1.3 Using camelCase
Apply it to variables, methods, properties and internal elements.
| Component | Example |
|---|---|
| Apex Methods | calculateTotal(), processInvoices() |
| Apex Variables | invoiceList, isValid, totalAmount |
| LWC Component Names | invoiceForm, customerOnboarding |
| LWC Properties | isLoading, recordId, errorMessage |
| Flow Variables | varB_IsValid, varT_CustomerName |
2.1.4 Using UPPER_SNAKE_CASE
Apply it to constants and immutable values.
| Component | Example |
|---|---|
| Apex Constants | MAX_RECORDS, DEFAULT_PAGE_SIZE |
| Apex Static Final Variables | API_VERSION, BATCH_SIZE |
| LWC Constants | MAX_FILE_SIZE, SUPPORTED_FORMATS |
2.1.5 Using kebab-case
Apply it in HTML references and web attributes.
| Component | Example |
|---|---|
| LWC Component Tags in HTML | <c-invoice-form>, <c-user-profile> |
| CSS Class Names | .container-main, .button-primary |
| Data Attributes | data-record-id, data-field-name |
2.2 Summary table: Case style by component
| Component | Case style | Example |
|---|---|---|
| Custom Object API Name | PascalCase | Invoice__c |
| Custom Field API Name | PascalCase | TotalAmount__c |
| Apex Class | PascalCase | InvoiceService |
| Apex Method | camelCase | calculateTotal() |
| Apex Variable | camelCase | invoiceList |
| Apex Constant | UPPER_SNAKE_CASE | MAX_RECORDS |
| Apex Trigger | PascalCase | InvoiceTrigger |
| Test Class | PascalCase | InvoiceServiceTest |
| Test Method | camelCase | testCalculate_Valid_Success |
| LWC Component Name | camelCase | invoiceForm |
| LWC in HTML Template | kebab-case | <c-invoice-form> |
| Flow API Name | PascalCase | Invoice_AfterInsert_Send |
| Flow Variable | camelCase | varB_IsValid |
| Permission Set | PascalCase | Invoicing_FullAccess |
| Record Type | PascalCase | InvoiceDraft |
| CSS Class | kebab-case | .btn-primary |
2.3 Custom Objects
Case style: PascalCase. API Name format: [ObjectName]__c.
| Object type | Prefix | API Name example | Label example |
|---|---|---|---|
| Business Object | — | Invoice__c | Invoice |
| Junction Object | — | AccountContact__c | Account Contact |
| Setting/Config | — | InvoiceSettings__c | Invoice Settings |
| Log/History | — | IntegrationLog__c | Integration Log |
| Managed Package | vtg__ | vtg__ProductCatalog__c | Product Catalog |
Mandatory rules
- USE PascalCase for the API Name.
- USE the singular (
Invoice__c, NOTInvoices__c). - USE descriptive English names.
- Junction Objects: concatenate the names in alphabetical order.
- Do NOT use abbreviations except for standard ones (Id, URL, API).
2.4 Custom Fields
Case style: PascalCase with no internal underscores. API Name format: [FieldName]__c.
| Type | Convention | ✓ Correct | ✗ Incorrect |
|---|---|---|---|
| Lookup (single) | Object name | Account__c | Account_Lookup__c |
| Lookup (with role) | [Role][Object] | BillingAccount__c | Billing_Account__c |
| External ID | [System]ExternalId | ComfiarExternalId__c | Comfiar_Ext_Id__c |
| Checkbox | Is / Has / Can | IsActive__c | Is_Active__c |
| Date | [Desc]Date | InvoiceDate__c | Invoice_Date__c |
| DateTime | [Desc]DateTime | ProcessedDateTime__c | Processed_Date_Time__c |
| Currency | Descriptive | TotalAmount__c | Total_Amount__c |
| Text | Descriptive | TaxExemptionCode__c | Tax_Exemption_Code__c |
2.5 Relationship Fields (Lookup and Master-Detail)
Relationship fields deserve special attention because they define how users "read" the data model.
2.5.1 Single relationship to an object
When an object has ONE relationship to another object, the API Name is simply the name of the target object:
1// Invoice__c has a lookup to Account2Field API Name: Account__c3Field Label: Account2.5.2 Multiple relationships to the same object
When an object has MULTIPLE relationships to the same object, use the pattern: [Role][ObjectName]__c.
1// Invoice__c has two lookups to Contact2PrimaryContact__c → Label: Primary Contact3BillingContact__c → Label: Billing Contact| ✓ Correct | ✗ Incorrect |
|---|---|
| PrimaryContact__c | Primary_Contact__c |
| SecondaryContact__c | Contact2__c |
| BillingAccount__c | Billing_Account__c |
| ApproverUser__c | Approver_User__c |
2.5.3 Common examples of role-based fields
| Scenario | API Name | Suggested label |
|---|---|---|
| Billing account | BillingAccount__c | Billing Account |
| Shipping account | ShippingAccount__c | Shipping Account |
| Primary contact | PrimaryContact__c | Primary Contact |
| Approver user | ApproverUser__c | Approver |
| Parent project | ParentProject__c | Parent Project |
| Original invoice | OriginalInvoice__c | Original Invoice |
2.6 Junction Objects
A Junction Object implements a many-to-many relationship between two objects.
2.6.1 Naming
Fundamental rule: use a business name, NOT a technical one.
| ✓ Correct | ✗ Incorrect |
|---|---|
| Application__c | CandidateJobJunction__c |
| Enrollment__c | StudentCourseJunction__c |
| Subscription__c | UserServiceJunction__c |
| Assignment__c | EmployeeProjectJunction__c |
| Membership__c | ContactGroupJunction__c |
2.6.2 Structure of a Junction Object
1Object: Application__c2Label: Application | Plural Label: Applications3
4Master-Detail fields:5 - Candidate__c (MD → Candidate__c)6 - JobPosition__c (MD → JobPosition__c)7
8Additional fields:9 - ApplicationDate__c (Date)10 - Status__c (Picklist: Pending, Approved, Rejected)2.6.3 Primary Master-Detail relationship
The first Master-Detail field created becomes the primary relationship. This determines ownership inheritance, cascade delete and Roll-up Summary availability.
2.7 Record Types
DeveloperName: PascalCase, with no __c suffix.
Pattern: [Object][Segment] or [Object][Process].
| Object | DeveloperName | Label |
|---|---|---|
| Account | AccountB2B | Account - B2B |
| Account | AccountB2C | Account - B2C |
| Invoice__c | InvoiceDraft | Invoice - Draft |
| Invoice__c | InvoicePosted | Invoice - Posted |
| Case | CaseSupport | Case - Support |
| Case | CaseBilling | Case - Billing |
2.8 Page Layouts
Pattern: [Object] Layout - [Variant].
| ✓ Correct | ✗ Incorrect |
|---|---|
| Invoice Layout - Draft | InvoiceDraft |
| Invoice Layout - Posted | Posted Invoice Layout |
| Account Layout - Partner | Partner Account Layout |
| Account Layout - Standard | Account Layout |
2.9 Apex Classes
Case style: PascalCase with a descriptive suffix based on the role.
| Type | Suffix | Example | Purpose |
|---|---|---|---|
| Service | Service | InvoiceService | Business logic |
| Selector | Selector | InvoiceSelector | SOQL queries |
| Domain | (plural) | Invoices | Object behavior |
| Trigger Handler | TriggerHandler | InvoiceTriggerHandler | Trigger logic |
| Controller | Controller | InvoiceController | LWC/Aura controller |
| Batch | Batch | InvoiceGenerationBatch | Batch processing |
| Schedulable | Scheduler | DailyInvoiceScheduler | Scheduled jobs |
| Queueable | Queueable | InvoiceSendQueueable | Async processing |
| Test | Test | InvoiceServiceTest | Unit tests |
| Test Data Factory | TestDataFactory | TestDataFactory | Test data creation |
| Utility | Util | TaxCalculationUtil | Utility methods |
| Exception | Exception | ValidationException | Custom exceptions |
| Invocable | Invocable | SendToAfipInvocable | Actions for Flow |
| Wrapper | Wrapper | InvoiceWrapper | Data transfer objects |
2.10 Apex Methods and Variables
| Element | Case Style | ✓ Correct | ✗ Incorrect |
|---|---|---|---|
| Methods | camelCase | calculateTotal() | CalculateTotal() |
| Local variables | camelCase | invoiceList | InvoiceList |
| Parameters | camelCase | invoiceId | InvoiceId |
| Constants | UPPER_SNAKE | MAX_RECORDS | maxRecords |
| Boolean vars | camelCase | isValid | IsValid |
| Collections | camelCase | invoices | Invoices |
2.11 Triggers
Case style: PascalCase. Format: [ObjectName]Trigger.
| ✓ Correct | ✗ Incorrect |
|---|---|
| InvoiceTrigger | invoiceTrigger |
| InvoiceLineTrigger | invoice_line_trigger |
2.12 Test Classes and Methods
Test Class: PascalCase → [ClassBeingTested]Test.
Test Method: camelCase → test[Method]_[Scenario]_[Result].
| Example | Description |
|---|---|
InvoiceServiceTest | Test class (PascalCase) |
testCalculateTotal_ValidData_ReturnsSum | Test method (camelCase) |
testValidateInvoice_MissingCAE_ThrowsException | Test method (camelCase) |
2.13 Validation Rules
Format: [Object]_[Field/Condition]_[RuleType].
| ✓ Correct | ✗ Incorrect |
|---|---|
| Invoice_TotalAmount_Required | invoice_total_required |
| Invoice_CAE_ValidFormat | invoiceCAEValidation |
| InvoiceLine_Quantity_Positive | VR_001 |
2.14 Permission Sets
Permission Set: [Feature/Object]_[AccessLevel].
Permission Set Group: [Role]_Permissions.
| Type | Pattern | Example |
|---|---|---|
| Full Access PS | [Object]_FullAccess | Invoicing_FullAccess |
| Read Only PS | [Object]_ReadOnly | Invoicing_ReadOnly |
| Feature PS | [Feature]_Access | ReportBuilder_Access |
| Integration PS | [System]_Integration | Comfiar_Integration |
| PS Group | [Role]_Permissions | BillingManager_Permissions |
2.15 Flows
API Name: PascalCase with underscores as separators.
Variables: camelCase with a type prefix.
| Flow type | Pattern | Example |
|---|---|---|
| Record-Triggered (Before) | [Obj]_Before[Event]_[Action] | Invoice_BeforeInsert_Validate |
| Record-Triggered (After) | [Obj]_After[Event]_[Action] | Invoice_AfterInsert_SendToAfip |
| Screen Flow | [Process]_ScreenFlow | InvoiceCreation_ScreenFlow |
| Autolaunched | [Process]_Autolaunched | InvoiceGeneration_Autolaunched |
| SubFlow | SubFlow_[Function] | SubFlow_CalculateTaxes |
| Scheduled | [Process]_Scheduled_[Freq] | InvoiceRetry_Scheduled_Hourly |
| Platform Event | [EventName]_Handler | InvoiceApproved_Handler |
2.16 Reports and Dashboards
Report and Dashboard names are visible to end users, so clarity and organization come first.
2.16.1 Report naming
Case style: Title Case with spaces (readable for users).
Format: [Area] – [Descriptive Name] ([Period]).
| ✓ Correct | ✗ Incorrect |
|---|---|
| Sales – Pipeline by Stage (Monthly) | SalesPipelineMonthly |
| Billing – Invoices Pending CAE | InvoicesPendingCAE |
| Support – Open Cases by Priority | OpenCasesByPriority |
| HR – Onboarding Q4 2025 | HR_Onboarding_Report |
2.16.2 Dashboard naming
Format: [Area] – Dashboard [Purpose].
| Example | Description |
|---|---|
| Sales – Executive Dashboard | Executive view of sales metrics |
| Billing – Operations Dashboard | Daily billing metrics |
| Support – SLA Dashboard | Service-level tracking |
| Marketing – Q4 Campaigns Dashboard | Campaign performance |
2.16.3 Folder naming
Format: [Area/Department] – [Topic].
| Folder example | Contents |
|---|---|
| Sales – Pipeline Reports | Sales pipeline reports |
| Billing – AFIP | AFIP/COMFIAR integration reports |
| Finance – Collections | Collections and aging reports |
| Executive – KPIs | Dashboards for leadership |
3Data Model
3.1 Standard Integration Fields
For objects that take part in integrations with external systems (such as COMFIAR, ERPs, etc.):
| Field | API Name | Type | Purpose |
|---|---|---|---|
| Integration Status | IntegrationStatus__c | Picklist | Sync state |
| Last Sync DateTime | LastSyncDateTime__c | DateTime | Last successful sync |
| Sync Error Message | SyncErrorMessage__c | Long Text | Error detail |
| Retry Count | SyncRetryCount__c | Number(3,0) | Sync attempts |
4Flow Standards
Flows account for roughly 60% of automation development on Salesforce.
4.1 Flow Variables
Case style: camelCase with a type prefix (varB_, varT_, etc.).
| Type | Prefix | Example | Use |
|---|---|---|---|
| Boolean | varB_ | varB_IsValidInvoice | Flags, decisions |
| Currency | varC_ | varC_TotalAmount | Monetary values |
| Date | varD_ | varD_InvoiceDate | Dates without time |
| DateTime | varDT_ | varDT_ProcessedAt | Timestamps |
| Number | varN_ | varN_LineCount | Counters |
| Text | varT_ | varT_CAENumber | Strings |
| Record | varR_ | varR_CurrentInvoice | Single record |
| Collection | varCol_ | varCol_InvoiceLines | List of records |
4.2 Flow Elements
Decisions
Case style: Sentence case (question in English).
| ✓ Correct | ✗ Incorrect |
|---|---|
| Is Valid Invoice? | Invoice_Check |
| Has Valid CAE? | CAE_VALIDATION |
| Exceeds Credit Limit? | verificarLimite |
Assignments
| Prefix | Use | Example |
|---|---|---|
SET | Assign a value | SET Invoice Status |
CALC | Calculate a value | CALC Total With Taxes |
INIT | Initialize collections | INIT Lines Collection |
ADD | Add to a collection | ADD to Update Collection |
LOG | Prepare logging data | LOG Error Details |
Data Elements
| ✓ Correct | ✗ Incorrect |
|---|---|
| Get Invoice Records | DATA_RETRIEVAL |
| Create Invoice Line | createLine |
| Update Invoice Status | Update1 |
| Delete Draft Invoices | eliminar_borradores |
4.3 Error Handling
- All Get/Create/Update/Delete Records elements.
- HTTP Callouts / External Services.
- Calls to SubFlows.
- Invocable Actions.
4.4 Flow Performance
Performance checklist:
- Use specific filters in Get Records elements.
- Limit the records returned (use LIMIT).
- Select only the fields you need.
- ONE Get Records per object (consolidate).
- NEVER DML inside loops: use collections.
- SubFlows for reusable logic.
- Maximum 50 elements per Flow.
- Fault paths on critical elements.
5Apex Development and TDD
5.1 Apex Class Structure
1/**2 * @description Service class for Invoice-related business logic3 * @author Vantegrate Development Team4 * @date 2025-12-015 */6public with sharing class InvoiceService { // PascalCase7
8 // UPPER_SNAKE_CASE for constants9 private static final Decimal IVA_RATE = 0.21;10 private static final Integer MAX_RETRY_COUNT = 3;11
12 // camelCase for methods13 public static Decimal calculateTotalWithTax(List<InvoiceLine__c> lines) {14 // camelCase for variables15 Decimal subtotal = 0;16 Decimal taxAmount = 0;17
18 for (InvoiceLine__c line : lines) {19 subtotal += line.Amount__c;20 }21
22 taxAmount = subtotal * IVA_RATE;23 return subtotal + taxAmount;24 }25}5.2 Trigger Handler Pattern
The trigger must be minimal and delegate all logic to the handler:
1// Trigger — PascalCase: [Object]Trigger2trigger InvoiceTrigger on Invoice__c (before insert, after insert) {3 new InvoiceTriggerHandler().run();4}1// Handler — PascalCase: [Object]TriggerHandler2public class InvoiceTriggerHandler extends TriggerHandler {3
4 public override void beforeInsert() {5 InvoiceService.validateInvoices((List<Invoice__c>) Trigger.new);6 }7
8 public override void afterInsert() {9 InvoiceService.sendToComfiar((List<Invoice__c>) Trigger.new);10 }11}6Lightning Web Components (LWC)
6.1 Component Naming
| Element | Case Style | JS example | HTML example |
|---|---|---|---|
| Component Name | camelCase | invoiceForm | <c-invoice-form> |
| JS Properties | camelCase | isLoading | — |
| JS Methods | camelCase | handleSave() | — |
| Constants | UPPER_SNAKE | MAX_LINES | — |
| Event Names | lowercase | 'save' | onsave |
| CSS Classes | kebab-case | — | .btn-primary |
| Data Attributes | kebab-case | — | data-line-id |
6.2 LWC Best Practices
- Use @api for public properties exposed to parents.
- Use @track only when necessary (reactive objects/arrays).
- Prefer getter methods over @track for computed values.
- Handle errors in wire methods.
- Use ShowToastEvent for user feedback.
- Avoid querySelector: use data-id and template refs.
- Implement loading states for async operations.
- Use UPPER_SNAKE_CASE constants for magic values.
7Security and Permissions
7.1 CRUD and FLS
In the example below, as user applies the checks automatically and you only need to catch the exception:
1Account myAcc = new Account(2 Name = 'Vantegrate Upgrade',3 AnnualRevenue = 500000 // Assume this field is read-only4);5try {6 // Automatically validates CRUD, FLS and Sharing Rules7 insert as user myAcc;8} catch (DmlException e) {9 // Robust handling of security errors10 for (Integer i = 0; i < e.getNumDml(); i++) {11 if (e.getDmlType(i) == StatusCode.INSUFFICIENT_ACCESS_OR_READONLY) {12 System.debug('Error: the user does not have permission');13 } else {14 System.debug('Other DML error: ' + e.getDmlMessage(i));15 }16 }17}In the example below, using WITH USER_MODE at the end of the SOQL query runs the checks automatically and you only need to catch the exception:
1try {2 // The query fails if the user lacks access to 'Phone' or 'Industry'3 List<Account> accs = [4 SELECT Id, Name, Phone5 FROM Account6 WHERE Industry = 'Technology'7 WITH USER_MODE8 ];9 System.debug('Records retrieved respecting security: ' + accs.size());10} catch (QueryException e) {11 // The message indicates which field or permission is missing12 System.debug('SOQL permission error: ' + e.getMessage());13}7.2 Sharing Model
| Keyword | Use |
|---|---|
with sharing | DEFAULT: respects sharing rules. Use for normal business logic. |
without sharing | Ignores sharing rules. Only for system operations (batch, integrations). |
inherited sharing | Inherits from the caller. Use for reusable utility classes. |
7.3 Security Checklist
- Declare the sharing model in every class.
- Check CRUD before DML operations.
- Check FLS before accessing sensitive fields.
- Use WITH USER_MODE in queries.
- Do not hardcode IDs.
- Sanitize user inputs.
- Use variable binding in SOQL (prevent injection).
- Avoid sensitive information in debug logs.
8PMD Rules
8.1 Critical Rules (Block Deploy)
| Rule | Description |
|---|---|
ApexUnitTestClassShouldHaveAsserts | Tests MUST have assertions. |
AvoidLogicInTrigger | Triggers MUST delegate to handlers. |
AvoidDmlStatementsInLoops | NEVER DML in loops. |
AvoidSoqlInLoops | NEVER SOQL in loops. |
ApexCRUDViolation | Check CRUD before DML. |
ApexSharingViolations | Declare sharing in classes. |
ApexSOQLInjection | Prevent SOQL injection. |
AvoidHardcodingId | No hardcoded IDs. |
8.2 Best-Practice Rules
| Rule | Description |
|---|---|
DebugsShouldUseLoggingLevel | Debug with a level: System.debug(LoggingLevel.INFO, msg). |
ApexAssertionsShouldIncludeMessage | Assertions with a descriptive message. |
MethodNamingConventions | Methods in camelCase. |
ClassNamingConventions | Classes in PascalCase. |
FieldNamingConventions | Variables in camelCase. |
OneDeclarationPerLine | One declaration per line. |
AvoidGlobalModifier | Avoid global (except for web services). |
9Versioning and Release Management
9.1 Semantic Versioning
Format: MAJOR.MINOR.PATCH.
| Component | Increment when | Example |
|---|---|---|
| MAJOR (X.0.0) | Breaking changes, major redesign | 2.0.0 → New data model |
| MINOR (x.Y.0) | New backward-compatible functionality | 2.1.0 → New integration |
| PATCH (x.y.Z) | Bug fixes, minor improvements | 2.1.1 → Fix validation rule |
9.2 Release Notes
Every release must document:
- Version number and date.
- New features.
- Changes to existing functionality.
- Bug fixes.
- Breaking changes (if any).
- Migration steps (if any).
- Updated dependencies.
10Documentation
10.1 ApexDoc for Classes
1/**2 * @description Service for invoice lifecycle management and AFIP integration3 * @author Vantegrate Development Team4 * @date 2025-12-015 * @version 2.06 */7public with sharing class InvoiceService {8
9 /**10 * @description Sends invoices to COMFIAR for AFIP authorization11 * @param invoices List of invoices to process12 * @return ProcessingResult Results including CAE numbers13 * @throws IntegrationException When COMFIAR is unavailable14 * @example15 * List<Invoice__c> invoices = [SELECT Id FROM Invoice__c];16 * InvoiceService.sendToComfiar(invoices);17 */18 public static ProcessingResult sendToComfiar(List<Invoice__c> invoices) {19 // Implementation20 }21}10.2 Flow Documentation
Every Flow must include in its Description:
1FLOW NAME: Invoice Authorization Automation2
3PURPOSE:4Sends new invoices to COMFIAR for AFIP authorization5and updates CAE information upon response.6
7TRIGGER:8Record-Triggered Flow on Invoice__c (After Insert)9
10INPUT REQUIREMENTS:11- Invoice with Customer, InvoiceDate, and at least one Line12
13ERROR HANDLING:14- Validation errors: Set ProcessingStatus__c = 'Error'15- COMFIAR errors: Log to IntegrationLog__c, alert admin16
17VERSION: 2.018LAST MODIFIED: 2025-12-0119AUTHOR: Vantegrate Development Team11Checklists and Templates
11.1 Pre-Deployment Checklist
- Every class has coverage ≥ 75%.
- Every test has meaningful assertions.
- PMD reports no critical violations.
- ApexDoc complete on public classes.
- Flows have fault paths on critical elements.
- No SOQL/DML in loops.
- Bulk testing completed (200+ records).
- Names follow the standard conventions.
- Security Review: CRUD/FLS verified.
- Release notes documented.
11.2 Code Review Checklist
- Code in English (variables, methods, comments).
- Correct naming per the standard.
- Triggers delegate to Handlers.
- Classes declare the sharing model.
- No hardcoded IDs.
- Error handling implemented.
- Appropriate logging with LoggingLevel.
- Tests cover positive and negative scenarios.
- Bulk processing implemented.
11.3 New Custom Object Checklist
- API Name in PascalCase and singular.
- Label and Plural Label defined.
- Description completed.
- ExternalId__c field created.
- IsActive__c field created.
- SourceSystem__c field created.
- LastProcessedDateTime__c field created.
- ProcessingStatus__c field created.
- Sharing model configured.
- Permission Sets updated.
- Page Layouts configured.
AAppendix A: Quick Naming Reference Table
| Element | Case Style | Pattern | Example |
|---|---|---|---|
| Custom Object | PascalCase | [Name]__c | Invoice__c |
| Custom Field | PascalCase | [Name]__c | TotalAmount__c |
| Apex Class | PascalCase | [Name][Suffix] | InvoiceService |
| Apex Method | camelCase | [verb][Object] | calculateTotal |
| Apex Variable | camelCase | [name] | invoiceList |
| Apex Constant | UPPER_SNAKE | [NAME] | MAX_RECORDS |
| Test Class | PascalCase | [Class]Test | InvoiceServiceTest |
| Test Method | camelCase | test[M]_[S]_[R] | testCalc_Valid_Ok |
| Trigger | PascalCase | [Object]Trigger | InvoiceTrigger |
| LWC Component | camelCase | [descriptive] | invoiceForm |
| LWC in HTML | kebab-case | <c-[name]> | <c-invoice-form> |
| LWC Property | camelCase | [name] | isLoading |
| LWC Constant | UPPER_SNAKE | [NAME] | MAX_FILE_SIZE |
| Flow API Name | PascalCase | [Obj]_[Action] | Invoice_SendToAfip |
| Flow Variable | camelCase | var[T]_[Name] | varB_IsValid |
| Flow Decision | Sentence | [Question]? | Is Valid? |
| Permission Set | PascalCase | [Obj]_[Access] | Invoicing_Admin |
| Validation Rule | PascalCase | [O]_[F]_[Rule] | Invoice_CAE_Required |
| Record Type | PascalCase | [Obj][Segment] | InvoiceDraft |
| Page Layout | Mixed | [Obj] Layout - [V] | Invoice Layout - Draft |
| CSS Class | kebab-case | .[name] | .btn-primary |
End of document
Vantegrate Standards Guide · Version 4.4














