Thursday 8 December 2016

Apex Design Patterns


Domain Model, "An object model of the domain that incorporates both behavior and data." “At its worst business logic can be very complex. Rules and logic describe many different cases and slants of behavior, and it's this complexity that objects were designed to work with.” Martin Fowler, EAA Patterns

Like the Service layer, the Domain Model provides a more granular level of code encapsulation and reuse within your application, such as complex validation, defaulting, and other logic relating to complex calculation and manipulation.

Apex triggers - Create, read, update, and delete (CRUD) operations, including undelete, occur on your custom objects as users or tools interact via the standard Salesforce UIs or one of the platform’s APIs. The operations are routed to the appropriate Domain class code corresponding to that object and operation.

Apex services - Service layer code should be easy to identify and make it easy to reuse code relating to one or more of the objects that each of its operations interacts with via Domain classes. This approach keeps the code in the service layer focused on orchestrating whatever business process or task it is exposing.

The Apex Domain class is consumed by the Apex trigger handler and Apex service method call.

Important: Remember that code relating to Visualforce controllers, Batch Apex, and API classes that you develop is encouraged to use functionality solely exposed via the Service layer operations. Thus, code written in the Domain layer is always indirectly invoked. Domain layer code is typically an internal business logic aspect of your application.


Design Considerations

Essentially, the Domain layer opens up OOP capabilities within Apex to your application but does so in a way that is aligned (mostly by naming conventions) with your application’s domain terms and concepts and the platform’s own best practices.

Bulkification - As with the Service layer, bulkification is a key design consideration on Force.com and has bearing on the domain layer’s design guidelines to ensure that domain class constructors, parameters, methods, and properties deal with data in terms of lists and not singular instances. This approach helps promote, and thus propagate further down the layers, this critical best practice more visibly. After all, no point in having a bulkified service if the rest of your application code does not support it.

Extension by containment - Domain logic must encapsulate both data and behavior. Apex represents data as sObjects. You can’t extend an sObject, but you can wrap it or contain it with another class that complements the data with appropriate behavioral code (methods, properties, and so on).

Naming conventions - Because the domain data is a data set or list as per the bulkification convention, your domain class ideally reflects this in its name, for example, public class Invoices.

OOP - In Force.com, one custom object cannot extend another in the same way classes do in OOP languages such as Java. Therefore, you often end up creating a number of custom objects that share similar aspects, sets of fields, and relationships. When defining your Domain classes for such objects, consider using inheritance or interfaces to abstract common behavioral aspects into a shared base class or interface, allowing you to create and reuse logic that applies across such objects. This unit uses some aspects of OOP. Ideally, you are familiar with some of the basics, such as inheritance and method overriding.

Security - Avoid using the with sharing or without sharing keywords on Domain Apex classes to ensure that the calling context drives this aspect. Typically, this is the Service class logic that, as per its design guidelines, must specify with sharing.

Separation of Concerns - Be consistent regarding where common types of domain logic, such as validation, defaulting, and calculations go. While it is possible to mix this in with other Domain logic solely related to database and trigger events, you have the option to split this logic across different methods in the Domain class. Consider if it is useful to expose this code to make it accessible in contexts not driven by database operations., such as services that provide validation or defaulting-only behavior.

Service layer is a key entry point to other layers and consumers(such as APIs).

Who Uses the Service Layer?

You might be tempted to say "all the cool kids" use a service layer, but technically the consumer of a service layer is called the "client." A client invokes your service layer code. These are not human interactions with the Service layer, but other pieces of code that interact with the user or system, such as a UI controller or Batch Apex.

Note: 

Apex triggers are missing because the logic belongs to your application’s Domain layer, which is closely aligned with the objects and thus manipulation of the records in your application. Domain logic is called both directly and indirectly within the Service layer and, of course, via the platform UI and APIs.

Design Considerations

Naming conventions - The Service layer must be abstract enough to be meaningful to a number of clients. This aspect often falls to the verbs and nouns you use in class, methods, and parameter names. Ensure that they are expressed in general terms of the application or task rather than relating to a specific client caller. For example, this method name is based on business operation InvoiceService.calculateTax(...) while this method name is based on a specific client usage operation InvoiceService.handleTaxCodeForACME(...). The second method name should leave you feeling a little uneasy.

Platform / Caller sympathy - Design method signatures that support the platform’s best practices, especially bulkification. One of the main concerns of all code on Force.com is bulkificaiton. Consider services that can be called with lists versus single parameter sets. For example, this method's parameters allow for bulkification InvoiceService.calculateTax(List<TaxCalulation> taxCalulations) while this method forces callers to call the method repeatedly InvoiceService.calculateTax(Invoice invoice, TaxInfo taxCodeInfo). Again, the second one should make you feel a little uneasy.

SOC considerations - Service layer code encapsulates task or process logic typically utilizing multiple objects in your application. Think of this as an orchestrator. In contrast, code relating specifically to validation, field values or calculations, which occur during record inserts, updates, and deletes, is the concern of the related object. Such code is typically written in Apex triggers and can remain there. Don't worry, we’ll introduce the Domain pattern for this type of code shortly

Security - Service layer code and the code it calls should by default run with user security applied. To ensure that this is the case, utilize the with sharing modifier on your Apex Service classes (especially important if you’re exposing such code via the global modifier). If Apex logic must access records outside of the user’s visibility, the code must explicitly elevate the execution context as briefly as possible. A good approach is to use a private Apex inner class with the without sharing modifier applied.

Marshalling - Avoid prescribing how aspects of interacting with the service layer are handled because certain aspects are better left to the callers of your service, for example, semantics like error handling and messaging. Callers often have their own means to interpret and handle these. For example, Visualforce uses <apex:pagemessages>, and Schedule jobs will likely use emails, Chatter posts, or logs to communicate errors. So in this case, it is typically best to leverage the default error-handling semantics of Apex by throwing exceptions. Alternatively, your service can provide partial database update feedback to the caller. In this case, devise an appropriate Apex class and return a list of that type. The system Database.insert method is a good example of this type of method signature.

Compound services - Although clients can execute multiple service calls one after another, doing so can be inefficient and cause database transactional issues. It’s better to create compound services that internally group multiple service calls together in one service call. It is also important to ensure that the service layer is as optimized as possible in respect to SOQL and DML usage. This does not mean that more granular services cannot be exposed; it just means that you should give the callers the option to use a more specific single service if needed.
.
Transaction management and statelessness - Clients of the service layer often have different requirements regarding the longevity of the process being undertaken and the information being managed. For example, a single request to the server and multiple requests split into separate scopes: the manage state (such as Batch Apex) or a complex UI that maintains its own page state across several requests. Given these variations on state management, it’s best to encapsulate database operations and service state within the method call to the service layer. In other words, make the service stateless to give calling contexts the flexibility to employ their own state management solutions. The scope of a transaction with the database should also be contained within each service method so that the caller does not have to consider this with its own SavePoints, for example.

Configuration - You might have common configuration or behavioral overrides in a service layer, such as providing control to allow the client to instruct the server layer not to commit changes or send emails. This scenario might be useful in cases where the client is implementing preview or what-if type functionality. Be sure to consider how you implement this consistently, perhaps as a method overload that takes a shared Options parameter, similar to the DML methods in Apex.

Note:
In Apex, database transactions are auto-committed if the request completes without error and rolled back in the event of an unhandled exception. However, allowing a request to complete with errors being thrown is not a desired user experience because the platform handling of these exceptions is often not all that accessible (Batch Apex jobs) or aesthetically pleasing (white page, black text) to end users. For this reason, developers often catch exceptions and route them accordingly. A potential side effect with this approach is that the platform sees this is a valid completion of the request and commits records that have been inserted or updated leading up to the error that occurred. By following the above service layer design principles regarding statelessness and transaction management, you can avoid this problem.

Important Points On Service Layer

1) Service layer should not have the error handling capability, only the caller should have the error handling capability
2) In salesforce if error occurs and it is not handled then salesforce will rollback the transaction. But from end user perspective we need to handle the errors and show user messages when any exception occurs.
3) Hence we need to use savepoint and try/catch semantics in the caller class method(for example: controller)

above point covered from below link 

https://trailhead.salesforce.com/apex_patterns_sl/apex_patterns_sl_learn_uow_principles


Unit Of Work

The Unit of Work is a design pattern that reduces repetitive code when implementing transaction management and the coding overheads of adhering to DML bulkification through extensive use of maps and lists.

The Unit of Work pattern used in this module is based on the pattern described by Martin Fowler: "Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems."


Apex Implementation of the Unit of Work Pattern

To include the Unit of Work in your service code methods, follow these steps.
  • Initialize a single Unit of Work and use it to scope all the work done by the service method.
          First we need to initilize the unit of work class with list or map of sobjects as shown below

04    fflib_SObjectUnitOfWork uow = new fflib_SObjectUnitOfWork(
05        new List<SObjectType> { OpportunityLineItem.SObjectType, Opportunity.SObjectType  }
06    );
  • Have the service layer logic register records with the Unit of Work when it executes.
          Second we have register the list to methods in unit of work class as mentioned below

          uow.registerDirty(oppLineItem);
  • Call the Unit of Work commitWork method to bulkify and execute the DML.
           Third commit the unit of work
            
28    // Commit Unit of Work
29    uow.commitWork();


To get more details on above points, please refer to below link

https://trailhead.salesforce.com/apex_patterns_sl/apex_patterns_sl_learn_uow_principles


Important Points On Domain Layer

We can implement below things in domain layer

1) Implementing field defaulting logic
2) Implementing validation logic
3) Implementing apex trigger logic
4) Implementing complex custom logic

Business Logic in the Domain Class vs. Service Class


Type of Application ConcernService or DomainExample
Making sure that fields are validated and defaulted consistently as record data is manipulated.DomainApply default discount policy to products as they are added.
Responding to a user or system action that involves pulling together multiple pieces of information or updating multiple objects. Mostly provides actions that can occur to a collection of records and coordinates everything that is needed to complete that action (potentially with other supporting services).ServiceCreate and calculate invoices from work orders. Might pull in price book information.
Handling changes to records that occur in the application as part of other related records changing or through the execution of a user or system action. For example, defaulting values as required. If changing one field affects another, it’s also updated.DomainHow the Account object reacts when an Opportunity is created or how the Discount is applied when the Opportunity discount process is run. Note: This sort of logic might start in the Service layer, but be better served in the Domain layer to manage the size and complexity of the service method size or improve reuse.
Handling of common behavior that applies across a number of different objects.DomainCalculate price on the opportunity product or work order product lines. Note: You could place this in a shared Domain base class, overriding the fflib_SObjectDomain method to hook into the Apex trigger events, with concrete Domain classes extending this class in turn with their behaviors.