This article is completing the official documentation on SAP Commerce best practices. It is based on many customer/partner development feedback experiences.
This list is not exhaustive. However, it can be used to watch project development to increase code quality and performance. Some tool or script could be used to ensure the respect of those rules as SONAR.
In the most case, this practice should and can be applied. But in rare case, you could have to break the rule. In this specific case, you should have strong argument and a validation from SAP Expert Service.
- Avoid as much as possible multiple extension dependency. For example: A->B/C and B->C.
- Respect architecture layer separation: Presentation, Business, Data Access
- No business code in Controller
- No business code in DAO
- Use Converter and Populator to translate Model (items) into DTO (beans)
- Reuse as much as possible SAP Commerce Data Model
- Don’t create a new field if the business name is compliant with Customer needs
- Don’t extend an item if the business is compliant with Customer needs
- Don’t use current session into ServiceLayer as much as possible instead put the object in parameter
- Service layer should independent from current session context
- Bad practice: CartModel cart = customCartCalculationCartService.computeCart()
- Good practice: customCartCalculationCartService.computeCart(CartModel cart)
- Don’t use Event System for load balancing back office tasks or high distributed system
- High risk of firing event chain reaction… (mind about cache invalidation)
- Better to use Cronjob running on one dedicated node in multi-thread
- Storefront Performance
- No database writing expect for Registration, Cart, Order
- AJAX calls for user tracking and personalizations
- OCC / REST API
- Must be used for incoming business logic request
- Must be stateless
- Database transaction safe (only one writing block per service exposed)
- API Registry
- Must be used for outcoming business logic request
- Integration API
- Must be used for data sync
- Outbound sync for sending data
- Inbound sync for receiving data
- No custom build or binary call
- As NPM for legacy storefront
- No filesystem access read or write
- Exception can be made for reading setting file from extension
- SAP Commerce POD can be reset at any time
- Disk I/O is limited
- Better to use Azure Blob Store, see azurecloud extension
- Avoid to use custom local caching strategy (ehCache / DTO Caching)
- SAP Commerce POD memory is limited
- Better to use high level caching strategy as CDN HTML or/and API caching
- Stream as much as possible heavy processing (large data import/export for example)
- SAP Commerce POD memory is limited
- Insert as much as possible log trace in custom code
- Remote debugging execution step by step is not possible
- Low level access on SAP Commerce POD is not possible by Customer/Partner
- Ensure that DAO/Flexible Search contains compatible Azure SQL functions
- For example: DATEDIFF, CONVERT, TOP
- Ensure that data model doesn’t allow/contain NULL value for an attribute
- By default Commerce Cloud/Azure SQL setting doesn’t handle it
- Asynchronous / data replication is preferable for back-end integration (SCPI)
- Limit Business Process/Event usage (high database write access and high thread consumption). Better to replace by asynchronous processing as Cronjob
- Incoming connection must be ended before 1 minutes
- Outcoming connection must be ended before 4 minutes
- Trace integration calls and setup WARN message when it exceeds KPI (OnpenSearch Monitoring)
- No nodeID assignation allowed. nodeGroup assignation must be used.
- nodeID is dynamic. Impossible to know if a nodeID will continue to exist.
Composable Storefront (Front)
SAP Commerce (Back)
- Prefix new class with project name, in order to distinct easily SAP Commerce core and customized code
- Write all the code in English and the comment too.
- Respect SAP Commerce code rules: eclipse configuration file
- Don’t create class with over 1500 lines of code
- Never use System.out or e.printStackTrace() (log4j2 should be used to log the actions and errors)
- Don’t use catch exception as conditional block (if-else). In other words, don’t add business code in catch block. It is better for performance to use if-else block
- Spring MVC Interceptors should be light in term of business complexity and resource consummation
- Use relative path instead of absolute path (java code, ant xml, and so on)
- Define new settings as simple as possible (local.properties):
- Don’t export settings which can be computed from others
- Don’t export settings which should be a constant in code
- JaloSession management
- Always close a JaloSession after using: JaloSession.getCurrentSession().close();
- If you cannot set a short timeout: JaloSession.getCurrentSession().setTimeout(10); // seconds
- Write/Add new DAO (FlexibleSearch) method instead of complex call service layer approach (Multi-service call to rebuild or compute a data)
- For no jointures and complex fetching data, use loading by example model instead of FlexibleSearch query
- Use TDD approach
- Write interface first
- Write unitary test case in second step.
- F.I.R.S.T rules (Fast, Independent, Repeatable, Self-Validating)
- Be relevant
- Implement mock of business (if required or useful)
- Implement code of business
- No big object into user session (PK or Reference is preferable)
- Never change database structure or data directly with SQL command
- Trace in detail external interface message exchange to help integration and debug (SOAP, REST, JMS, and so on)
- Respect trace level
- ERROR: a true error that should be fix as soon as possible
- WARN: a strange behavior that should not happen
- INFO: indicate the end or start of big computing step
- DEBUG: trace any relevant change for debugging
- Spring Core (*spring.xml)
- bean id must be unique. use alias tag to override bean definition.
- parent attribute should never reference an alias. alias should be used only for attribute injection not for inheritance injection.
- split big spring file into several little ones: tag import, attribute resource
- Data Model (*-items.xml)
- Prefix new item with project name, in order to distinct easily hybris table and customized table
- For each new item associate a deployment table
- Deployment type code between 0 and 10000 are reserved to hybris.
- Associate a jalo class for each type, even if those classes are not later customized.
- Avoid ordered relations as much as possible
- Add description for type, attribute or relation
- Avoid customize jalo class as much as possible (use service layer instead)
- Use RelationTypes whenever possible
- Use “modelService.create(NewsModel.class)” instead of “new NewsModel()”
- Avoid to use dynamic attribute (poor performance, not hot deployment ready)
- DTO (*-beans.xml)
- Add property instead of creating a new data bean (easier for Converter/Populator and MVC customization layers)
- Web Service
- Don’t customize model to adapt REST web service (/ws410/rest//)
- Use OCC approach (Controller approach) to create new REST web service: Customizing the Commerce Web Services
- Create a new extension to store all codes related to web service exposed: Provider Services
- Storefront Controller
- Make sure all @ExceptionHandler is writing in log file: LOG.error(exception.getMessage(), exception);
- CMS/HTML Design
- Ask a web agency SAP Commerce certified to provide a well-suitable HTML code: Guidelines for design agencies
- Avoid pop-up element into CMS component
- Think about automatic non regression tests: name each HTML tag in page with unique id
- Don’t integrate HTML code directly in CMS Page, split first in CMS Component
- Create a new CMS type when UX is different. Different rendering can be handled by style attribue (styleClass).
- Security
- Never build a FlexibleSearch by concatenating the query code and the data (Instead: use passing parameter)
- Don’t store HTML code in database (It could lead to XSS issue)
- Use strong symmetric encryption when user ID has to be sent through URL parameter (even in HTTPS)
- Don’t use @Transactional on too large data (as long list of elements)
- Never use writable java static variable, high risk of multi-threading race condition issue for: importation, synchronization, indexation, HTTP request.
- Don’t use == to compare two Item/PK. Better to use code/unique id for the comparaison. == doesn’t ensure that two Item/PK is equal (cache + pointer comparaison)
- Don’t use == to compare two String (pointer). Better to use equals() method (value).
- Business Process
- Never use getEventService().publishEvent() into Action class. We should use getBusinessProcessService().startProcess()
- Top 10 Recommendations for Improving the Performance of your Commerce Cloud Promotion Engine
- Using Dynatrace to Manage and Optimize the Performance of your SAP Commerce Cloud Solution
- SOLR: relevant small document size instead of default large document size (longer indexation/search time)
- 3rd party : async call should be used instead of sync calls (thread retention => memory consumption)
- Data sync into SAP Commerce should be done when it is possible (product info, price, stock and so on)
- Cronjob : sequential execution instead of concurrency execution (peak DTU usage)
- Azure Blob storage access instead of write disk access (high I/O consumption)
- CDN caching instead of local pod caching (less memory for business logic computation)
- Dedicate flexible search instead of complex Items fetching (generate lot of micro SQL requests)
- In very high order placement volume, Business Process is not the best option. Cronjob approach should be studied.
- SQL Query
- SQL request should NOT contain date transformation as DATEADD/DATETRUNC. Query cache can be used in this case. Better to format date in Java code and add it in parameter.
- Date parameter should be truncated to optimize query cache hit.
- Never store core product code in git repository
- Deactivate SAP Commerce modules, extensions, and tenants are not used in solution.
- Don’t commit binary or generated files: classes, gensrc, etc…
- Don’t commit Jalo classes generated
- Commit only source code tested and be able to compile
- Clean auto-generated extension (ant extgen) or module (ant modulegen)
- Remove not used feature: web context, hmc configuration, and so on.
- Add release and build number in each custom extension: .build.number
When best practices are known and applied, SAP Commerce Cloud development complexity can be drastically reduced. It help also to smooth the upgrading the solution on the latest version.
And Customer/Partner can request SAP Expert Service packages where this best practice application can be audited in your solution:
文章来源: https://blogs.sap.com/2023/12/18/advanced-development-best-practices-for-sap-commerce-cloud/
如有侵权请联系:admin#unsafe.sh