• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Apex Enterprise Patterns: Building Strong Foundations
 

Apex Enterprise Patterns: Building Strong Foundations

on

  • 810 views

Any structure expected to stand the test of time and change needs a strong foundation! Software is no exception. Engineering your code to grow in a stable and effective way is critical to your ability ...

Any structure expected to stand the test of time and change needs a strong foundation! Software is no exception. Engineering your code to grow in a stable and effective way is critical to your ability to rapidly meet the growing demands of users, new features, technologies, and platform capabilities. Join us to obtain architect-level design patterns for use in your Apex code to keep it well factored, easy to maintain, and in line with platform best practices. You'll follow a Force.com interpretation of Martin Fowler's Enterprise Architecture Application patterns, and the practice of Separation of Concerns.

Statistics

Views

Total Views
810
Views on SlideShare
810
Embed Views
0

Actions

Likes
1
Downloads
25
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Apex Enterprise Patterns: Building Strong Foundations Apex Enterprise Patterns: Building Strong Foundations Presentation Transcript

    • Building Strong Foundations Apex Enterprise Patterns Andrew Fawcett, FinancialForce.com, CTO @andyinthecloud
    • All about FinancialForce.com Revolutionizing the Back Office #1 Accounting, Billing and PSA Apps on the Salesforce platform ▪ Native apps ▪ San Francisco HQ, 595 Market St ▪ R&D in San Francisco, Harrogate UK, and Granada ES ▪ We are hiring! Meet us at Rehab!
    • What's wrong with this picture?
    • What's wrong with this picture? public with sharing class MyController { public String theId; public MyController(ApexPages.StandardController standardController) { theId = (String) ApexPages.currentPage().getParameters().get('id'); } public PageReference actionCheckInvoices() { // Read the Account record Account accountRecord = [select Id, Name from Account where Id = :theId]; // Do some processing on the Account record ... then update it update accountRecord; return null; } } public with sharing class MyBatchJob implements Database.Batchable<SObject> { public void execute(Database.batchableContext info, List<Account> accounts) { for(Account account : accounts) { MyController myController = new MyController(new ApexPages.StandardController(account)); myController.actionCheckInvoices(); } } public Database.QueryLocator start(Database.BatchableContext info) { ... } public void finish(Database.batchableContext info) { ... } } Developer “A” writes an Apex Controller first Developer “B” writes an Apex Batch job later.
    • So what was wrong with that picture? MyController MyController Issue Use of ApexPages.currentPage() Unnecessary and fragile, utilize instead stdController.getId() method Error handling No try/catch error handling on controller method Developer “A” MyBatchJob Issue Use of ApexPages.currentPage() Is not available in a Batch Apex context, the constructor code will give an exception. SOQL Query and DML Governors Calling the controller method in a loop will cause a SOQL query and DML governor issues. Error Handling No try/catch error handling in the the execute method Separation of Concerns Developer A did not originally develop the controller logic expecting or anticipating Developer B’s would in the future try to reuse it from a Batch Context as well. They did not consider correct Separation of Concerns… Developer “B”
    • Pattern Checklist Separation of Concerns Service Layer Domain Layer Selector Layer ☐ ☐ ☐ ☐
    • So what is “Separation of Concerns” then? “The goal is to design systems so that functions can be optimized independently of other functions, so that failure of one function does not cause other functions to fail, and in general to make it easier to understand, design and manage complex interdependent systems” Wikipedia, “Separation of Concerns”
    • So what is “DRY” then? Don’t Repeat Yourself “Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.” Wikipedia, “Don’t repeat yourself (DRY)”
    • Design Patterns for SOC & Force.com Best Practice Service Layer Domain Layer ▪ Yet another Wrapper / Trigger pattern! Selector Layer Reference Martin Fowler ▪ http://martinfowler.com/eaaCatalog/ ▪ Author of “Patterns of Enterprise Application Architecture” Reference ▪ http://wiki.developerforce.com/page/Apex_Enterprise_Patterns_-_Separation_of_Concerns
    • Demo! “takeaway” a Sample Force.com Application! GitHub: financialforcedev/fflib-apex-common-samplecode
    • Sample Application, what’s on the menu? Platform Feature Patterns Used Custom Buttons Building UI logic and calling Service Layer code from Controllers Batch Apex Reusing Service and Selector Layer code from with a Batch context Integration API Exposing an Integration API via Service Layer using Apex and REST Apex Triggers Factoring your Apex Trigger logic via the Domain Layer (wrappers) VisualForce Remoting Exposing Service Layer code to HTML5 / JavaScript libraries such as JQuery GitHub: financialforcedev/fflib-apex-common-samplecode
    • Pattern Checklist Separation of Concerns Service Layer Domain Layer Selector Layer ☑ ☐ ☐ ☐
    • Introducing the Service Layer
    • Introducing the Service Layer Naming Convention ▪ Suffix with ‘Service’, e.g. OpportunitiesService ▪ Methods named by purpose not usage, e.g. applyDiscounts
    • Introducing the Service Layer Clear Code Factoring ▪ Encapsulates Processes / Tasks ▪ Caller Context Agnostic
    • Introducing the Service Layer Defined Responsibilities ▪ Supports Bulkifcation ▪ Transaction management
    • Developing and calling a Service Layer public with sharing class AccountService { public static void checkOutstandingInvoices(Set<Id> accountIds) { // Read the Account records List<Account> accountRecords = [select Id, Name from Account where Id in :accountIds]; // Do some processing on the Account and Invoice records ... then update them. update accountRecords; } } Developer “A” follows Service Layer pattern. AccountService.cls Service Contract public PageReference actionCheckInvoices() { try { // Process the Account record AccountService.checkOutstandingInvoices(new Set<Id> { theId }); } catch (Exception e) { ApexPage.addMessages(e); } return null; } Developer “A” writes Controller code to consume the Service. MyController.cls public void execute(Database.batchableContext info, List<Account> accounts) { try { // Process Account records Set<Id> accountIds = new Map<Id, Account>(accounts).keySet(); AccountService.checkOutstandingInvoices(accountIds); } catch (Exception e) { emailError(e); } } MyBatch.cls Developer “B” then reuses the Developer “A” code safely.
    • Code Walkthrough : Sample Services Managing DML and Transactions ▪ Unit of Work Pattern Classes OpportunitiesService.cls
    • Code Walkthrough : Custom Buttons Custom Buttons ▪ Detail and List View ▪ Calling Visualforce Controller Code Visualforce Controllers and Pages ▪ Error Handling ▪ Interacts with Service Layer • Utilize bulkified methods • Assume transaction containment • Catch exceptions and display them on the page Classes and Pages OpportunityApplyDiscountController.cls • opportunityapplydiscount.page • opportunityapplydiscounts.page OpportunityCreateInvoiceController.cls • opportunitycreateinvoice.page • opportunitycreateinvoices.page
    • CodeHandling Walkthrough : Batch Apex ▪ Error Classes ▪ Interacts with Service Layer CreatesInvoicesJob.cls • Utilize bulkified methods • Assume transaction containment • Catch exceptions and logs them for later notificaiton
    • CodeHandling Walkthrough : Exposing an Integration API ▪ Error Classes • Pass business logic exceptions to caller to handle • Assume transaction containment OpportunitiesResource.cls OpportunitiesService.cls ▪ Exposing the API • To Apex Developers > Mark Service class and methods as global! – Package to apply Apex versioning of the API • To Web / Mobile Developers > Create RESTful API around Service layer
    • Code Walkthrough : Visualforce Remoting An “Opportunities Discount Console” Classes OpportunityConsoleController.cls ▪ Developer uses a Rich HTML5 Client Library, such as JQuery • Is not using traditional Visualforce markup or action functions on the controller ▪ Utilizing static “remote” methods on the controller (stateless controller) • Able to consume the Service layer functions also! • Assumes transactional integrity • Assumes the caller (JavaScript client) to handle exceptions
    • Pattern Checklist Separation of Concerns Service Layer Domain Layer Selector Layer ☑ ☑ ☐ ☐
    • Introducing the Domain Layer
    • Introducing the Domain Layer Naming Convention ▪ Name uses plural name of object, e.g. Opportunities
    • Introducing the Domain Layer Clear Code Factoring ▪ Encapsulates Validation / Defaulting of Fields ▪ Wraps Apex Trigger Logic in Apex Class (Trigger/Wrapper Pattern)
    • Introducing the Domain Layer Defined Responsibilities ▪ Enforces Bulkifcation for logic ▪ Platform security best practice (honors Users profile) ▪ Encapsulates ALL logic / behavior for each object • e.g. onValidate, onBeforeInsert and applyDiscount
    • Introducing the Domain Layer : Apex Trigger Flow
    • Code Walkthrough : Domain Layer : Apex Triggers What no code?!? ☺ Triggers OpportunitiesTrigger.trigger OpportunityLineItemsTrigger.trigger
    • Code Walkthrough : Domain Layer : Domain Classes Bulkified Wrappers ▪ Base class fflib_SObjectDomain ▪ Apex Trigger Callers ▪ Support for DML Free Testing ▪ Able to apply Object Orientated Programming Apex Classes Opportunities.cls OpportunityLineItems.cls Accounts.cls
    • Code Walkthrough : Domain Layer : Service Callers Apex Service Callers ▪ Create Domain Instances ▪ Bulkified Calls Apex Classes OpportunitiesService.cls
    • Code Walkthrough : Domain : Extends vs Interfaces Extending Apex Domain Classes ▪ Extend or adjust existing behavior of classes of a similar nature • Base class Chargeable ensures cost is recalculated on insert and update • DeveloperWorkItems Domain Class extends to provide its own calc logic Implementing Apex Domain Interfaces ▪ Good for applying behavior to different types of classes • Interface InvoiceService.ISupportInvoicing • Implemented by Opportunities Domain Class
    • Code Walkthrough : Domain Class Extension Chargeable Base Class ▪ Apply to Custom Objects recording Work ▪ Require hours and cost calculations ▪ Performs recalculation on insert and update
    • Pattern Checklist Separation of Concerns Service Layer Domain Layer Selector Layer ☑ ☑ ☑ ☐
    • Introducing the Selector Layer
    • Introducing the Selector Layer Naming Convention ▪ Plural object name suffixed by Selector • e.g. OpportunitiesSelector
    • Introducing the Selector Layer Clear Code Factoring ▪ Encapsulates Query Logic
    • Introducing the Selector Layer Defined Responsibilities ▪ Consistency over queried fields ▪ Platform security best practice ▪ Encapsulates ALL query logic
    • Code Walkthrough : Selector Layer Encapsulate Query Fields and Logic ▪ Base class fflib_SObjectSelector ▪ Defines Common Fields ▪ Default SOQL Helpers, FieldSet Support Apex Classes OpportunitiesSelector.cls OpportunityLineItemsSelector.cls ProductsSelector.cls PricebooksSelector.cls PricebookEntriesSelector.cls
    • Code Walkthrough : Selector Layer : Callers Service Layer Logic : OpportunitiesSelector.selectByIdWithProducts Apex Class OpportunitiesService.cls Domain Layer Logic : AccountsSelector.selectByOpportunity Apex Class Opportunities.cls
    • Code Walkthrough : Selector Layer : Callers Batch Apex : OpportunitiesSelector.queryLocatorReadyToInvoice Apex Class CreatesInvoicesJob.cls
    • Pattern Checklist Separation of Concerns Service Layer Domain Layer Selector Layer ☑ ☑ ☑ ☑
    • Summary
    • Summary
    • When is SOC / DRY appropriate (a rough guide)? Solution / Code Base Size Developers Requirements Scope Number of Client Types and Interactions SOC/DRY Appropriate? Small 1 to 2 • Well known and unlikely to change One off solutions Limited number of objects • • • • • Standard UI Simple VF / Triggers No Batch Mode No API No Mobile Typically not Well known but may need to evolve rapidly Growing number objects and processes interacting Product deliverable or larger duration projects • • • • • Standard UI Advanced VF / JQuery Batch Mode API (on roadmap) Mobile (on roadmap) Worth considering Scope driven by multiple customers and user types Large number of objects Generic product or solution aimed at Mid to Enterprise market with Customer or Partner Integrations. Growing development team! • • • • • • Standard UI Advanced VF / JQuery Batch Mode Developer / Partner API Mobile Clients New Platform Feature Ready, Chatter Actions! • • Small to Medium 1 to 6 • • • Large >6 • • • • Definite benifits
    • Other Design Patterns Helping with SOC/DRY Alternative Domain Layer Patterns ▪ ‘Apex Trigger Pattern’ (Tony Scott) • http://developer.force.com/cookbook/recipe/trigger-pattern-for-tidy-streamlined-bulkified-triggers ▪ ‘Salesforce Apex Wrapper Class’ (Mike Leach) • http://www.embracingthecloud.com/2013/09/06/SalesforceApexWrapperClass.aspx ▪ ‘Trigger Architecture Framework’ (Hari Krishnan) • http://krishhari.wordpress.com/category/technology/salesforce/apex-triggers/
    • Andrew Fawcett CTO, @andyinthecloud