With Unit Of Work

Before we take a closer look at how the FinancialForce Apex Enterprise Pattern library has helped us implement this pattern, let's first take a look at the following revised example of the code shown earlier. This code utilizes a new Apex class called Application. This class exposes a static property and method to create an instance of a Unit Of Work.

The source code for this chapter includes the FinancialForce Apex Enterprise Pattern library, as well as the FinancialForce Apex Mocks library it depends on. We will explore the Apex Mocks library in a later chapter, where we will focus on writing unit tests for each of the patterns introduced in this book.

The fflib_ISObjectUnitOfWork Apex Interface is used to expose the features of the Unit Of Work pattern to capture the database work as records are created, thus the remaining logic is more focused and avoids Map and List and repeated iterations over the imported data shown in the previous example. It also internally bulkifies the work (DML) for the caller. Finally, the commitWork method call performs the actual DML work in the correct dependency order while applying transaction management.

Consider the following code:

  // Construct a Unit Of Work to capture the following working 
  fflib_ISObjectUnitOfWork uow =
Application.UnitOfWork.newInstance(); // Create Driver__c records Map<String, Driver__c>driversById = new Map<String, Driver__c>(); for(DriverDatadriverData : seasonsData.drivers){ Driver__c driver = new Driver__c( Name = driverData.name, DriverId__c = driverData.driverId, Nationality__c = driverData.nationality, TwitterHandle__c = driverData.twitterHandle); uow.registerNew(driver); driversById.put(driver.DriverId__c, driver); } for(SeasonDataseasonData : seasonsData.seasons){ // Create Season__c record Season__c season = new Season__c( Name = seasonData.year, Year__c = seasonData.year); uow.registerNew(season); for(RaceDataraceData : seasonData.races){ // Create Race__c record Race__c race = new Race__c(Name = raceData.name); uow.registerNew(race, Race__c.Season__c, season); for(ContestantDatacontestantData : raceData.contestants){ // Create Contestant__c record Contestant__c contestant = new Contestant__c( ChampionshipPoints__c = contestantData.championshipPoints, DNF__c = contestantData.dnf, Qualification1LapTime__c =
contestantData.qualification1LapTime, Qualification2LapTime__c =
contestantData.qualification2LapTime, Qualification3LapTime__c =
contestantData.qualification3LapTime); uow.registerNew (contestant, Contestant__c.Race__c, race); uow.registerRelationship(contestant,
Contestant__c.Driver__c,
driversById.get(contestantData.driverId)); } } } // Insert records registered with uow above uow.commitWork();

The following is the implementation of the Application class and the UnitOfWork static property. It leverages a simple factory class that dynamically creates instances of the fflib_SObjectUnitOfWork class through the newInstance method:

public class Application  
{ 
  // Configure and create the UnitOfWorkFactory for 
  //  this Application 
  public static final fflib_Application.UnitOfWorkFactory UnitOfWork = 
new fflib_Application.UnitOfWorkFactory( new List<SObjectType> { Driver__c.SObjectType, Season__c.SObjectType, Race__c.SObjectType, Contestant__c.SObjectType}); }

The fflib_Application.UnitOfWorkFactory class exposes the newInstance method that internally creates a new fflib_SObjectUnitOfWork instance. This is not directly exposed to the caller; instead, the fflib_ISObjectUnitOfWork interface is returned (this design aids the mocking support we will discuss in a later chapter). The purpose of this interface is to provide the methods used in the preceding code to register records for insert, update, or delete, and implement the commitWork method.

I recommend that you create a single application Apex class like the one shown previously, where you can maintain the full list of objects used in the application and their dependency order; as your application's objects grow, it will be easier to maintain.

The fflib_ISObjectUnitOfWork interface has the following methods in it. The preceding example uses the registerNew and registerRelationship methods to insert records and ensure that the appropriate relationship fields are populated. Review the documentation of these methods in the code for more details. The following screenshot shows a summary of the methods:

Call the registerDirty method with a SObject record you want to update and the registerDeleted method to delete a given SObject record. You can also call a combination of the registerNew, registerDirty, and registerDeleted methods.

The previous diagram only shows a selection of the full methods available. Consult the source code and comments for further information. For example, recent contributions from the community have included support for including sending platform events (we will cover these in more detail later in the book). There is also more extensibility through virtual methods that can be overridden to listen to or modify its behavior.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.249.158