From 6a19ee05eb79ac9eafd4c0680bea8dea1a42687a Mon Sep 17 00:00:00 2001 From: awesomeandrey Date: Thu, 28 Nov 2024 14:20:57 +0000 Subject: [PATCH] Minlopro: code conventions in MD file --- CODECONVENTIONS.md | 175 ++++++++++++++++++ README.md | 48 ++--- manifests/destructiveChangesPost.xml | 5 - .../ViewLogs.customPermission-meta.xml | 5 + .../Minlopro_Logger.permissionset-meta.xml | 4 + .../DigEx1/brandingSets/buildYourOwn.json | 2 +- .../experiences/DigEx1/routes/carDetail.json | 2 +- .../experiences/DigEx1/routes/carList.json | 2 +- .../DigEx1/routes/carRelatedList.json | 2 +- .../experiences/DigEx1/views/carDetail.json | 2 +- .../experiences/DigEx1/views/carList.json | 2 +- .../DigEx1/views/carRelatedList.json | 2 +- .../applications/MinloproConsole.app-meta.xml | 4 +- .../MinloproContactsConnection.cls | 2 +- .../SFDC_CCF_Echo.connectedApp-meta.xml | 4 + .../SalesforceOwnerId__c.field-meta.xml | 2 +- .../profiles/Minlopro User.profile-meta.xml | 20 ++ 17 files changed, 245 insertions(+), 38 deletions(-) create mode 100644 CODECONVENTIONS.md create mode 100644 src/minlopro-core/main/customPermissions/ViewLogs.customPermission-meta.xml diff --git a/CODECONVENTIONS.md b/CODECONVENTIONS.md new file mode 100644 index 00000000..023dc977 --- /dev/null +++ b/CODECONVENTIONS.md @@ -0,0 +1,175 @@ +# Code Conventions + +- [Introduction](#introduction) +- [General Best Practices](#general-best-practices) +- [Code Conventions](#code-conventions) + - [Apex Classes](#apex-classes) + - [Naming Conventions](#naming-conventions) + - [Critical Coding Standards](#critical-coding-standards) + - [Class Design](#class-design) + - [Unit Tests](#unit-tests) + - [LWC (Lightning Web Components)](#lwc-lightning-web-components) + - [Naming Conventions](#naming-conventions-1) + - [Critical Coding Standards](#critical-coding-standards-1) + - [Aura Components](#aura-components) + - [Naming Conventions](#naming-conventions-2) + - [Critical Coding Standards](#critical-coding-standards-2) + +## Introduction + +This guide serves as a comprehensive reference for Salesforce developers, covering best practices and conventions to ensure consistency, maintainability, and scalability across projects. + +--- + +## General Best Practices + +- Every declarative metadata component (flow, custom object, custom field etc.) must have clear & meaningful description provided. +- Configure/wWrite polite, user-friendly error messages. + - Example: Prefer “Please provide a value for the Status field” over “Missing required field.” +- Avoid hardcoding sensitive data like IDs or credentials. +- Design your logic to handle large data sets and avoid hitting Salesforce's governor limits. + +--- + +## Code Conventions + +### Apex Classes + +#### Naming Conventions + +1. **Classes**: + - Use PascalCase (e.g., `AccountTriggerHandler`). + - Test classes should append `Test` to the name (e.g., `AccountServiceTest`). +2. **Variables**: + - Use camelCase (e.g., `recordIndex`). + - Avoid single-character variables except in loop counters. +3. **Methods**: + - Start with a lowercase letter and use camelCase (e.g., `fetchCustomerRecords`). +4. **Constants**: + - Use uppercase with underscores (e.g., `MAX_LIMIT`). + +#### Critical Coding Standards + +1. Use **PascalCase** for class names and **camelCase** for method and variable names. +2. Write one trigger per object and delegate logic to handler classes. +3. Always bulkify your code to handle collections of records efficiently. +4. Avoid SOQL or DML operations inside loops. +5. Use `Queueable` Apex for asynchronous processing when logic doesn’t need to run immediately. +6. Never hardcode IDs, user names, or sensitive data in your code. +7. Always check for **CRUD** and **FLS** permissions before performing DML or SOQL operations. +8. Use `try-catch` blocks for error handling, and throw custom exceptions for clarity. +9. Use `addError()` in triggers to provide user-friendly validation error messages. +10. Avoid SOQL queries without `WHERE` clauses or `LIMIT` to prevent retrieving excessive records. +11. Use `RecordType.DeveloperName` instead of `RecordType.Name` for better locale-independent queries. +12. Write descriptive comments for methods, classes, and complex logic to improve readability. +13. Use **Separation of Concerns**: divide logic into service, controller, and utility classes. +14. Mock data and external calls in unit tests to avoid dependency on dynamic data. +15. Avoid HTTP callouts within loops; batch them or use Asynchronous Apex. + +#### Class Design + +Follow the separation of concerns (SoC) principle: + +- **Controller Classes**: Handle UI-related logic. +- **Service Classes**: Contain business logic. +- **Selector Classes**: Perform SOQL queries. + +Example Class Structure: + +```apex +public with sharing class AccountService { + public void processAccounts(List accounts) { + // Business logic + } +} +``` + +#### Unit Tests + +1. Ensure every test method has clear, descriptive names that indicate the purpose of the test. +2. Aim for **100% code coverage**, with at least **85% coverage** as the minimum standard. +3. Write unit tests for both **positive** and **negative** scenarios to cover all use cases. +4. Use `Test.startTest()` and `Test.stopTest()` to reset governor limits and isolate test execution. +5. Create all necessary test data programmatically within the test method using utility classes or static methods. +6. Never rely on existing data in the database for tests - avoid `@SeeAllData=true` annotation. +7. Use mocking frameworks like **ApexMocks** to mock data, external services, and dependent methods. +8. Avoid using real DML operations in tests where possible; use mock objects to test business logic. +9. Test **bulk operations** by inserting or updating 200 records to simulate real-world scenarios. +10. Include meaningful **assertions** to validate expected outcomes. +11. Test for exceptions explicitly using `Assert.fail` or `try-catch` blocks. +12. Avoid hardcoding IDs, record names, or other sensitive data in test methods. +13. Verify CRUD and FLS permissions in tests to simulate different user profiles and permissions. +14. Use test classes to validate that SOQL and DML operations respect governor limits and query performance. + +--- + +### LWC (Lightning Web Components) + +#### Naming Conventions + +1. Use **camelCase** for JavaScript variables and methods (e.g., `handleButtonClick`). +2. Use descriptive names for public properties and annotate them with `@api` (e.g., `@api accountId`). +3. Use meaningful event names prefixed by the component name (e.g., `accountSelected`). +4. Use PascalCase for class names in JavaScript (e.g., `AccountOverview`). +5. Prefer [SLDS](https://www.lightningdesignsystem.com) CSS classes over custom ones for styling purposes. +6. For reusable components, append `-util` or `-helper` to the name (e.g., `date-picker-util`). +7. Use `handle` for event handler names (e.g., `handleSaveClick`). +8. Define constant values in uppercase with underscores (e.g., `MAX_ITEMS`). +9. Use `camelCase` for HTML template bindings and JavaScript properties (e.g., `isVisible`). +10. Avoid abbreviations in names unless widely recognized (e.g., use `calculateTotal`, not `calcTotal`). +11. Use singular or plural naming based on the context (e.g., `product` for a single item, `products` for lists). + +#### Critical Coding Standards + +1. Always use `@api` to define public properties and methods explicitly. +2. Avoid hardcoding object or field names; use dynamic binding or Lightning Data Service (LDS). +3. Use two-way data binding (`getter` and `setter`) for calculated or reactive properties. +4. Avoid business logic in components; delegate to Apex or utility classes for maintainability. +5. Do not manipulate the DOM directly; rely on framework methods and lifecycle hooks. +6. Use `template.querySelector` only when necessary, and avoid global selectors. +7. Always clean up resources like intervals, event listeners, or timers in the `disconnectedCallback`. +8. Follow HTML structure conventions: slot attributes first, system properties next, and event handlers last. +9. Use `import` for sharing JavaScript utilities across components (e.g., `import { calculateTax } from 'c/utils'`). +10. Leverage CSS custom properties for theming instead of inline styles. +11. Use `lightning` components wherever possible instead of custom implementations (e.g., `lightning-input`). +12. Avoid circular dependencies by properly structuring imports and exports. +13. Use the `wired` decorator (`@wire`) to connect to Salesforce data and cache results for efficiency. +14. Validate user input at both the component level and in the backend (Apex). +15. Ensure every event dispatched uses `CustomEvent` and bubbles only when necessary. + +--- + +### Aura Components + +#### Naming Conventions + +1. Use **camelCase** for attribute names (e.g., `recordId`). +2. Use **PascalCase** for component names (e.g., `AccountDetails`). +3. Use a descriptive name for component events with an appropriate suffix (e.g., `onAccountSelect`). +4. Prefer [SLDS](https://www.lightningdesignsystem.com) CSS classes over custom ones for styling purposes. +5. Name application events descriptively and append `Evt` (e.g., `AccountSelectedEvt`). +6. Append `Container` to the name of wrapper components (e.g., `AccountContainer`). +7. Prefix custom CSS classes with the component name to avoid global conflicts (e.g., `accountDetails__header`). +8. Use the same name for event and handler where applicable (e.g., `saveButtonClick` for `onSaveButtonClick`). +9. Use `handle` for JavaScript handler functions (e.g., `handleAccountSave`). +10. Constants in JavaScript should be named in uppercase with underscores (e.g., `MAX_RECORDS`). +11. Avoid abbreviations in names unless they are widely recognized (e.g., use `Component` instead of `Cmp`). +12. Use singular or plural naming based on the purpose (e.g., `account` for one record, `accounts` for collections). + +#### Critical Coding Standards + +1. Always use **attributes** with proper `type` definitions (e.g., `type="String"`). +2. Define default values for attributes where applicable using the `default` attribute. +3. Minimize business logic in the controller; delegate logic to helper methods. +4. Use `event.getParam()` and avoid directly accessing event parameters for flexibility. +5. Avoid hardcoding field and object names; use dynamic references or design patterns. +6. Use `action.setParams()` and avoid passing too many parameters in Apex methods. +7. Validate data at both the client and server-side for security and consistency. +8. Use `aura:if` sparingly; prefer dynamic expressions in `aura:iteration`. +9. Always handle `callback` responses from server-side controllers to manage state or errors. +10. Dispatch meaningful and user-friendly error messages to the UI on server-side errors. +11. Avoid deep nesting of components; aim for flatter hierarchies for better readability. +12. Cache frequently used data in component-level attributes to reduce server calls. +13. Use descriptive comments for each function, especially helper methods and server calls. + +--- diff --git a/README.md b/README.md index cc485631..895f5c70 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,20 @@ [![Release](https://github.com/awesomeandrey/minlopro-dx/actions/workflows/release_workflow.yml/badge.svg?branch=main)](https://github.com/awesomeandrey/minlopro-dx/actions/workflows/release_workflow.yml) [![Reset Destructive Manifests](https://github.com/awesomeandrey/minlopro-dx/actions/workflows/reset_destructive_manifests.yml/badge.svg)](https://github.com/awesomeandrey/minlopro-dx/actions/workflows/reset_destructive_manifests.yml) +- [About](#about) +- [Prerequisites](#prerequisites) +- [Branches](#branches) + - [Release Branch Preparation](#release-branch-preparation) +- [Managing Environment Variables](#managing-environment-variables) +- [Scripts in `package.json`](#scripts-in-packagejson) +- [Useful Commands](#useful-commands) +- [Code Convention](#code-convention) + ## About - - Minlopro - This is a blueprint repository for a typical Salesforce org-based project which is accompanied with CI/CD automations. - +Minlopro + +This is a blueprint repository for a typical Salesforce org-based project which is accompanied with CI/CD automations. ## Prerequisites @@ -24,7 +32,7 @@ for configuring `$JAVA_HOME` environment variable. Additionally install utility tools as follows: [`jq`](https://www.baeldung.com/linux/jq-command-json), [`xmllint`](https://www.baeldung.com/linux/xmllint), [`xmlstarlet`](https://xmlstar.sourceforge.net). -Run `bash ./scripts/deploy/build.sh` in order to load project dependencies. +Run `bash ./scripts/deploy/build.sh` in order to load project dependencies (including [Salesforce CLI](https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_unified.htm)). Look through the pre-configured GitHub Workflows/Actions located in `.github/workflows/` folder. @@ -82,20 +90,6 @@ Follow the steps below: This process ensures a structured flow of features into releases, maintaining stability and predictability in release management. -## Useful Commands - -_Deploy Codebase_ - -``` -npm run sf:manifest:create && npm run src:deploy:full -``` - -_Publish Community_ - -``` -sf community publish --name "DigEx" --target-org "$SCRATCH_ORG_ALIAS" -``` - ## Managing Environment Variables Environment variables are useful for deploying metadata components with secrets or org-specific settings (e.g. @@ -122,6 +116,16 @@ E.g. you can execute particular script passing in ORG alias: npm run src:push -- -o "$SCRATCH_ORG_ALIAS" ``` -Please, refer -to [Salesforce CLI](https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_unified.htm) -for more information. +## Useful Commands + +_Deploy Codebase_ + +``` +npm run sf:manifest:create && npm run src:deploy:full +``` + +_Publish Community_ + +``` +sf community publish --name "DigEx" --target-org "$SCRATCH_ORG_ALIAS" +``` diff --git a/manifests/destructiveChangesPost.xml b/manifests/destructiveChangesPost.xml index c3ab9190..43bf4084 100644 --- a/manifests/destructiveChangesPost.xml +++ b/manifests/destructiveChangesPost.xml @@ -1,9 +1,4 @@ - - Minlopro_App_Logo - Minlopro_App_Logo_min - ContentAsset - 61.0 diff --git a/src/minlopro-core/main/customPermissions/ViewLogs.customPermission-meta.xml b/src/minlopro-core/main/customPermissions/ViewLogs.customPermission-meta.xml new file mode 100644 index 00000000..0ba89d48 --- /dev/null +++ b/src/minlopro-core/main/customPermissions/ViewLogs.customPermission-meta.xml @@ -0,0 +1,5 @@ + + + false + + diff --git a/src/minlopro-core/main/permissionsets/Minlopro_Logger.permissionset-meta.xml b/src/minlopro-core/main/permissionsets/Minlopro_Logger.permissionset-meta.xml index a6e5506d..11cc5d81 100644 --- a/src/minlopro-core/main/permissionsets/Minlopro_Logger.permissionset-meta.xml +++ b/src/minlopro-core/main/permissionsets/Minlopro_Logger.permissionset-meta.xml @@ -12,6 +12,10 @@ true LoggerSettings__c + + true + ViewLogs + Grants access to logger module features. This PS should be primarily used by developer(s). false diff --git a/src/minlopro-digex/main/experiences/DigEx1/brandingSets/buildYourOwn.json b/src/minlopro-digex/main/experiences/DigEx1/brandingSets/buildYourOwn.json index 62cd9a83..dd7b3bdd 100644 --- a/src/minlopro-digex/main/experiences/DigEx1/brandingSets/buildYourOwn.json +++ b/src/minlopro-digex/main/experiences/DigEx1/brandingSets/buildYourOwn.json @@ -7,7 +7,7 @@ "ActionColor" : "#2574A9", "BorderColor" : "rgb(216, 221, 230)", "CardBackgroundColor" : "rgba(255, 255, 255, 0)", - "CompanyLogo" : "/file-asset/MinloproAppLogoMin?v=1&height=300&width=300", + "CompanyLogo" : "/file-asset/MinloproAppLogo?v=1&height=300&width=300", "DetailTextColor" : "rgb(84, 105, 141)", "ErrorFontColor" : "#ff9e9e", "HeaderFonts" : "Montserrat", diff --git a/src/minlopro-digex/main/experiences/DigEx1/routes/carDetail.json b/src/minlopro-digex/main/experiences/DigEx1/routes/carDetail.json index 0bcca41d..0adf3621 100644 --- a/src/minlopro-digex/main/experiences/DigEx1/routes/carDetail.json +++ b/src/minlopro-digex/main/experiences/DigEx1/routes/carDetail.json @@ -6,7 +6,7 @@ "id" : "51933273-2f0e-489b-8704-2634bf18c891", "label" : "Car Detail", "objectApiName" : "Car__c", - "routeType" : "detail-a0B", + "routeType" : "detail-a07", "type" : "route", "urlPrefix" : "car" } \ No newline at end of file diff --git a/src/minlopro-digex/main/experiences/DigEx1/routes/carList.json b/src/minlopro-digex/main/experiences/DigEx1/routes/carList.json index 3e6c2a71..7106a89c 100644 --- a/src/minlopro-digex/main/experiences/DigEx1/routes/carList.json +++ b/src/minlopro-digex/main/experiences/DigEx1/routes/carList.json @@ -6,7 +6,7 @@ "id" : "883da7e1-0418-4f44-9bd2-4660bc3e6250", "label" : "Car List", "objectApiName" : "Car__c", - "routeType" : "list-a0B", + "routeType" : "list-a07", "type" : "route", "urlPrefix" : "car" } \ No newline at end of file diff --git a/src/minlopro-digex/main/experiences/DigEx1/routes/carRelatedList.json b/src/minlopro-digex/main/experiences/DigEx1/routes/carRelatedList.json index c7f16459..38a11fe1 100644 --- a/src/minlopro-digex/main/experiences/DigEx1/routes/carRelatedList.json +++ b/src/minlopro-digex/main/experiences/DigEx1/routes/carRelatedList.json @@ -6,7 +6,7 @@ "id" : "250ff930-16dc-476c-ab11-1a8f96b26b53", "label" : "Car Related List", "objectApiName" : "Car__c", - "routeType" : "relatedlist-a0B", + "routeType" : "relatedlist-a07", "type" : "route", "urlPrefix" : "car" } \ No newline at end of file diff --git a/src/minlopro-digex/main/experiences/DigEx1/views/carDetail.json b/src/minlopro-digex/main/experiences/DigEx1/views/carDetail.json index 681fd5af..65fe32b0 100644 --- a/src/minlopro-digex/main/experiences/DigEx1/views/carDetail.json +++ b/src/minlopro-digex/main/experiences/DigEx1/views/carDetail.json @@ -62,5 +62,5 @@ } ], "themeLayoutType" : "BIGuMbINxUUPKhG01SUcMMJNvZRHRb", "type" : "view", - "viewType" : "detail-a0B" + "viewType" : "detail-a07" } \ No newline at end of file diff --git a/src/minlopro-digex/main/experiences/DigEx1/views/carList.json b/src/minlopro-digex/main/experiences/DigEx1/views/carList.json index 3718ef21..60676446 100644 --- a/src/minlopro-digex/main/experiences/DigEx1/views/carList.json +++ b/src/minlopro-digex/main/experiences/DigEx1/views/carList.json @@ -42,5 +42,5 @@ } ], "themeLayoutType" : "BIGuMbINxUUPKhG01SUcMMJNvZRHRb", "type" : "view", - "viewType" : "list-a0B" + "viewType" : "list-a07" } \ No newline at end of file diff --git a/src/minlopro-digex/main/experiences/DigEx1/views/carRelatedList.json b/src/minlopro-digex/main/experiences/DigEx1/views/carRelatedList.json index efd57f5f..c45425fb 100644 --- a/src/minlopro-digex/main/experiences/DigEx1/views/carRelatedList.json +++ b/src/minlopro-digex/main/experiences/DigEx1/views/carRelatedList.json @@ -35,5 +35,5 @@ } ], "themeLayoutType" : "BIGuMbINxUUPKhG01SUcMMJNvZRHRb", "type" : "view", - "viewType" : "relatedlist-a0B" + "viewType" : "relatedlist-a07" } \ No newline at end of file diff --git a/src/minlopro/main/applications/MinloproConsole.app-meta.xml b/src/minlopro/main/applications/MinloproConsole.app-meta.xml index dbe8e8cd..53dd4046 100644 --- a/src/minlopro/main/applications/MinloproConsole.app-meta.xml +++ b/src/minlopro/main/applications/MinloproConsole.app-meta.xml @@ -55,8 +55,8 @@ experimentation. Large - false - false + true + true true false diff --git a/src/minlopro/main/classes/salesforce-connect-custom-adapter/MinloproContactsConnection.cls b/src/minlopro/main/classes/salesforce-connect-custom-adapter/MinloproContactsConnection.cls index ad508b3c..d047c983 100644 --- a/src/minlopro/main/classes/salesforce-connect-custom-adapter/MinloproContactsConnection.cls +++ b/src/minlopro/main/classes/salesforce-connect-custom-adapter/MinloproContactsConnection.cls @@ -107,7 +107,7 @@ global class MinloproContactsConnection extends DataSource.Connection { columns.add( DataSource.Column.get( 'SalesforceOwnerId', - 'Salesforce Owner Id', + 'Salesforce Owner ID', '', true, true, diff --git a/src/minlopro/main/connectedApps/SFDC_CCF_Echo.connectedApp-meta.xml b/src/minlopro/main/connectedApps/SFDC_CCF_Echo.connectedApp-meta.xml index 9805f50c..6e89c1de 100644 --- a/src/minlopro/main/connectedApps/SFDC_CCF_Echo.connectedApp-meta.xml +++ b/src/minlopro/main/connectedApps/SFDC_CCF_Echo.connectedApp-meta.xml @@ -12,13 +12,17 @@ false false false + false false + false + false @SF_USERNAME Full RefreshToken BYPASS + false specific_lifetime:1:HOURS Minlopro - Custom Auth. Provider & NC diff --git a/src/minlopro/main/objects/SalesforceContact__x/fields/SalesforceOwnerId__c.field-meta.xml b/src/minlopro/main/objects/SalesforceContact__x/fields/SalesforceOwnerId__c.field-meta.xml index be27784b..d2d5e48a 100644 --- a/src/minlopro/main/objects/SalesforceContact__x/fields/SalesforceOwnerId__c.field-meta.xml +++ b/src/minlopro/main/objects/SalesforceContact__x/fields/SalesforceOwnerId__c.field-meta.xml @@ -6,7 +6,7 @@ false false false - + 18 User.ExternalId__c User diff --git a/src/minlopro/main/profiles/Minlopro User.profile-meta.xml b/src/minlopro/main/profiles/Minlopro User.profile-meta.xml index 0875c2b4..34e0c86a 100644 --- a/src/minlopro/main/profiles/Minlopro User.profile-meta.xml +++ b/src/minlopro/main/profiles/Minlopro User.profile-meta.xml @@ -53,6 +53,26 @@ VisualWorkflow true + + standard-Account + DefaultOn + + + standard-Contact + DefaultOn + + + standard-Opportunity + DefaultOn + + + standard-Lead + DefaultOn + + + SalesforceContact__x + DefaultOn + Salesforce true