Skip to content

Commit c1e27ad

Browse files
switch from jekyll to mkdocs for pages site
1 parent 679e082 commit c1e27ad

23 files changed

Lines changed: 227 additions & 145 deletions

.github/workflows/deploy.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Deploy MkDocs to GitHub Pages
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
deploy:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout repository
16+
uses: actions/checkout@v4
17+
18+
- name: Set up Python
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: "3.x"
22+
23+
- name: Install MkDocs Material
24+
run: pip install mkdocs-material
25+
26+
- name: Deploy to GitHub Pages
27+
run: mkdocs gh-deploy --force

docs/01-Introduction-to-the-Separation-of-Concerns-Design-Principle.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
---
2-
layout: default
32
title: "1) Introduction to the Separation of Concerns Design Principle"
4-
nav_order: 2
53
---
64

75
# Introduction to the Separation of Concerns Design Principle
@@ -19,15 +17,15 @@ In the Salesforce Ecosystem there are three major areas of concern we ideally sh
1917

2018
_**The Service Layer:**_
2119

22-
[The Service Layer](./07-The-Service-Layer) should house 100% of your non-object specific business logic (object specific logic is most often handled by the domain layer). This is, the logic that is specific to your organizations specific business rules. Say for instance you have a part of your Salesforce App that focuses on Opportunity Sales Projections and the Opportunity Sales Projection App looks at the Oppotunity, Quote, Product and Account objects. You might make an OpportunitySalesProjection_Service apex class that houses methods that have business logic that is specific to your Opportunity Sales Projection App. More information on the [Service Layer here.](./07-The-Service-Layer)
20+
[The Service Layer](./07-The-Service-Layer.md) should house 100% of your non-object specific business logic (object specific logic is most often handled by the domain layer). This is, the logic that is specific to your organizations specific business rules. Say for instance you have a part of your Salesforce App that focuses on Opportunity Sales Projections and the Opportunity Sales Projection App looks at the Oppotunity, Quote, Product and Account objects. You might make an OpportunitySalesProjection_Service apex class that houses methods that have business logic that is specific to your Opportunity Sales Projection App. More information on the [Service Layer here.](./07-The-Service-Layer.md)
2321

2422
_**The Domain Layer:**_
2523

26-
[The Domain Layer](./10-The-Domain-Layer) houses your individual objects (database tables) trigger logic. It also houses object specific validation logic, logic that should always be applied on the insert of every record for an object and object specific business logic (like how a task my be created for a specific object type, etc). If you used the Account object in your org you should create a Domain class equivalent for the Account object through the use of a trigger handler class of some sort. More information on the [Domain Layer here](./10-The-Domain-Layer).
24+
[The Domain Layer](./10-The-Domain-Layer.md) houses your individual objects (database tables) trigger logic. It also houses object specific validation logic, logic that should always be applied on the insert of every record for an object and object specific business logic (like how a task my be created for a specific object type, etc). If you used the Account object in your org you should create a Domain class equivalent for the Account object through the use of a trigger handler class of some sort. More information on the [Domain Layer here](./10-The-Domain-Layer.md).
2725

2826
_**The Selector Layer:**_
2927

30-
[The Selector Layer](./13-The-Selector-Layer) is responsible for querying your objects (database tables) in Salesforce. Selector layer classes should be made for each individual object (or grouping of objects) that you intend to write queries for in your code. The goal of the selector layer is to maintain query consistency (consistency in ordering, common fields queried for, etc) and to be able to reuse common queries easily and not re-write them over and over again everywhere.
28+
[The Selector Layer](./13-The-Selector-Layer.md) is responsible for querying your objects (database tables) in Salesforce. Selector layer classes should be made for each individual object (or grouping of objects) that you intend to write queries for in your code. The goal of the selector layer is to maintain query consistency (consistency in ordering, common fields queried for, etc) and to be able to reuse common queries easily and not re-write them over and over again everywhere.
3129

3230
---
3331

@@ -57,4 +55,4 @@ All of the code examples in this repo are examples of SoC in action. You can che
5755

5856
### Next Section
5957

60-
[Part 2: Introduction to the Apex Common Library](./02-Introduction-to-the-Apex-Common-Library)
58+
[Part 2: Introduction to the Apex Common Library](./02-Introduction-to-the-Apex-Common-Library.md)

docs/02-Introduction-to-the-Apex-Common-Library.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
---
2-
layout: default
32
title: "2) Introduction to the Apex Common Library"
4-
nav_order: 3
53
---
64

75
# Introduction to the Apex Common Library
@@ -27,9 +25,9 @@ Unfortunately it's not that simple. This library doesn't just automatically do t
2725

2826
### The Four Major Classes
2927
1) **[fflib_Application.cls](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_Application.cls) -** This Application class acts as a way to easily implement the Factory pattern for building the different layers when running your respective applications within your org (or managed package). When I say "Application" for an org based implementation this could mean a lot of things, but think of it as a grouping of code that represents a specific section of your org. Maybe you have a service desk in your org, that service desk could be represented as an "Application". This class and the factory pattern are also what makes the Apex Mocks Library work, without implementing it, Apex Mocks will not work.
30-
2) **[fflib_SObjectDomain.cls](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_SObjectDomain.cls) -** This houses the base class that all Domain classes you create will extend. The many methods within this class serve to make your life considerably easier when building your domain classes, for each object that requires a trigger, out. You can check out my [Apex Common Domain Layer Implementation Guide](./11-Implementing-The-Domain-Layer-with-the-Apex-Common-Library) for more details.
31-
3) **[fflib_SObjectSelector.cls](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_SObjectSelector.cls) -** This houses the base class that all Selector classes you create will extend. The many methods within this class will serve to make your life a ton easier when implementing a selector classes for your various objects in your org. You can check out my [Apex Common Selector Layer Implementation Guide](./14-Implementing-the-Selector-Layer-with-the-Apex-Common-Library).
32-
4) **[fflib_SObjectUnitOfWork.cls](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_SObjectUnitOfWork.cls) -** This houses the logic to implement the [Unit of Work design pattern](https://www.codeproject.com/Articles/581487/Unit-of-Work-Design-Pattern) in your code. There a ton of useful methods within it that will make your life developing on the platform quite a bit simpler. For more information on the fflib_SObjectUnitOfWork class and the concept itself, please refer to my [guide on how to use the Unit of Work Pattern in Salesforce](./05-The-Unit-of-Work-Pattern).
28+
2) **[fflib_SObjectDomain.cls](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_SObjectDomain.cls) -** This houses the base class that all Domain classes you create will extend. The many methods within this class serve to make your life considerably easier when building your domain classes, for each object that requires a trigger, out. You can check out my [Apex Common Domain Layer Implementation Guide](./11-Implementing-The-Domain-Layer-with-the-Apex-Common-Library.md) for more details.
29+
3) **[fflib_SObjectSelector.cls](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_SObjectSelector.cls) -** This houses the base class that all Selector classes you create will extend. The many methods within this class will serve to make your life a ton easier when implementing a selector classes for your various objects in your org. You can check out my [Apex Common Selector Layer Implementation Guide](./14-Implementing-the-Selector-Layer-with-the-Apex-Common-Library.md).
30+
4) **[fflib_SObjectUnitOfWork.cls](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_SObjectUnitOfWork.cls) -** This houses the logic to implement the [Unit of Work design pattern](https://www.codeproject.com/Articles/581487/Unit-of-Work-Design-Pattern) in your code. There a ton of useful methods within it that will make your life developing on the platform quite a bit simpler. For more information on the fflib_SObjectUnitOfWork class and the concept itself, please refer to my [guide on how to use the Unit of Work Pattern in Salesforce](./05-The-Unit-of-Work-Pattern.md).
3331

3432
---
3533

@@ -54,4 +52,4 @@ Unfortunately it's not that simple. This library doesn't just automatically do t
5452
---
5553

5654
### Next Section
57-
[Part 3: The Factory Pattern](./03-The-Factory-Method-Pattern)
55+
[Part 3: The Factory Pattern](./03-The-Factory-Method-Pattern.md)

docs/03-The-Factory-Method-Pattern.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
---
2-
layout: default
32
title: "3) The Factory Method Pattern"
4-
nav_order: 4
53
---
64

75
# The Factory Method Pattern
@@ -74,7 +72,7 @@ public with sharing class Task_Service_Impl implements Task_Service_Interface
7472
}
7573
```
7674

77-
Right now you might be kinda shook... at least I know I was the first time I implemented it, lol. How on Earth is this possible?? How can so much code be reduced to so little? The first thing we do is instantiate a new [domain class](./10-The-Domain-Layer) (domain classes are basically just kinda fancy trigger handlers, but more on that later) using our Application class (our factory class) simply by sending it record ids. The Application factory class generates the object specific Domain class by determining the set of recordIds object type using the Id.getSObjectType() method that Salesforce makes available in Apex. Then by implementing the `Task_Creator_Interface` interface on each of the objects domain classes I'm guaranteeing that if something is an instance of the `Task_Creator_Interface` they will have a method called createTasks! Depending on the use case this can take hundreds of lines of code and reduce it to almost nothing. It also helps in the Separation of Concerns area by making our services much more abstract. It delegates logic more to their respective services or domains instead of somewhere the logic probably doesn't belong.
75+
Right now you might be kinda shook... at least I know I was the first time I implemented it, lol. How on Earth is this possible?? How can so much code be reduced to so little? The first thing we do is instantiate a new [domain class](./10-The-Domain-Layer.md) (domain classes are basically just kinda fancy trigger handlers, but more on that later) using our Application class (our factory class) simply by sending it record ids. The Application factory class generates the object specific Domain class by determining the set of recordIds object type using the Id.getSObjectType() method that Salesforce makes available in Apex. Then by implementing the `Task_Creator_Interface` interface on each of the objects domain classes I'm guaranteeing that if something is an instance of the `Task_Creator_Interface` they will have a method called createTasks! Depending on the use case this can take hundreds of lines of code and reduce it to almost nothing. It also helps in the Separation of Concerns area by making our services much more abstract. It delegates logic more to their respective services or domains instead of somewhere the logic probably doesn't belong.
7876

7977
---
8078

@@ -86,7 +84,7 @@ Basically it reduces your need to declare concreate class/object types in your c
8684

8785
### Where is it used in the Apex Common Library
8886

89-
It's leveraged heavily by the fflib_Application class, which you can [find out more about here.](./04-The-fflib_Application-Class)
87+
It's leveraged heavily by the fflib_Application class, which you can [find out more about here.](./04-The-fflib_Application-Class.md)
9088

9189
---
9290

@@ -100,4 +98,4 @@ The following code example in the repo is an example of how the factory pattern
10098

10199
### Next Section
102100

103-
[Part 4: The fflib\_Application Class](./04-The-fflib_Application-Class)
101+
[Part 4: The fflib\_Application Class](./04-The-fflib_Application-Class.md)

docs/04-The-fflib_Application-Class.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
---
2-
layout: default
32
title: "4) The fflib_Application Class"
4-
nav_order: 5
53
---
64

75
# The fflib_Application Class
@@ -11,7 +9,7 @@ nav_order: 5
119
---
1210
### What is the fflib_Application class?
1311

14-
Quality question... I mean honestly wtf is this thing? Lol, sorry, let's figure it out together. The fflib_Application class is around for two primary purposes. The first is to allow you an extremely abstract way of creating new instances of your [unit of work](./05-The-Unit-of-Work-Pattern), [service layer](./08-Implementing-the-Service-Layer-with-the-Apex-Common-Library), [domain layer](./11-Implementing-The-Domain-Layer-with-the-Apex-Common-Library) and [selector layer](./14-Implementing-the-Selector-Layer-with-the-Apex-Common-Library) in the [Apex Common Library](./02-Introduction-to-the-Apex-Common-Library) through the use of [the factory pattern](./03-The-Factory-Method-Pattern). The second is that implementing this application class is imperative if you want to leverage the Apex Mocks unit testing library. It depends on this Application Factory being implemented.
12+
Quality question... I mean honestly wtf is this thing? Lol, sorry, let's figure it out together. The fflib_Application class is around for two primary purposes. The first is to allow you an extremely abstract way of creating new instances of your [unit of work](./05-The-Unit-of-Work-Pattern.md), [service layer](./08-Implementing-the-Service-Layer-with-the-Apex-Common-Library.md), [domain layer](./11-Implementing-The-Domain-Layer-with-the-Apex-Common-Library.md) and [selector layer](./14-Implementing-the-Selector-Layer-with-the-Apex-Common-Library.md) in the [Apex Common Library](./02-Introduction-to-the-Apex-Common-Library.md) through the use of [the factory pattern](./03-The-Factory-Method-Pattern.md). The second is that implementing this application class is imperative if you want to leverage the Apex Mocks unit testing library. It depends on this Application Factory being implemented.
1513

1614
Most importantly though, if you understand how interfaces, inheritance and polymorphism work implementing this class allows you to write extremely abstract Salesforce implementations, which we'll discuss more in sections below
1715

@@ -151,7 +149,7 @@ public with sharing class SomeClass{
151149
}
152150
```
153151
---
154-
2) [newInstance(fflib_SObjectUnitOfWork.IDML dml)](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_Application.cls#L71) - This creates a new instance of the unit of work using the SObjectType list passed in the constructor and a new IDML implementation to do custom DML work not inherently supported by the [fflib_SObjectUnitOfWork class](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_SObjectUnitOfWork.cls). More info on the [IDML interface here](./06-The-fflib_SObjectUnitOfWork-Class)
152+
2) [newInstance(fflib_SObjectUnitOfWork.IDML dml)](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_Application.cls#L71) - This creates a new instance of the unit of work using the SObjectType list passed in the constructor and a new IDML implementation to do custom DML work not inherently supported by the [fflib_SObjectUnitOfWork class](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_SObjectUnitOfWork.cls). More info on the [IDML interface here](./06-The-fflib_SObjectUnitOfWork-Class.md)
155153

156154
_**newInstance(fflib_SObjectUnitOfWork.IDML dml) Example Method Call**_
157155
```
@@ -222,7 +220,7 @@ public with sharing class SomeClass{
222220
}
223221
```
224222
---
225-
4) **_[newInstance(List <SObjectType> objectTypes, fflib_SObjectUnitOfWork.IDML dml)](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_Application.cls#L104)_** - This creates a new instance of the unit of work and overwrites the SObject type list passed in the constructor so you can have a custom order if you need it and a new IDML implementation to do custom DML work not inherently supported by the [fflib_SObjectUnitOfWork class](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_SObjectUnitOfWork.cls). More info on the [IDML interface here](./06-The-fflib_SObjectUnitOfWork-Class)
223+
4) **_[newInstance(List <SObjectType> objectTypes, fflib_SObjectUnitOfWork.IDML dml)](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_Application.cls#L104)_** - This creates a new instance of the unit of work and overwrites the SObject type list passed in the constructor so you can have a custom order if you need it and a new IDML implementation to do custom DML work not inherently supported by the [fflib_SObjectUnitOfWork class](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_SObjectUnitOfWork.cls). More info on the [IDML interface here](./06-The-fflib_SObjectUnitOfWork-Class.md)
226224

227225
_**newInstance(List<SObjectType> objectTypes, fflib_SObjectUnitOfWork.IDML dml) Example Method Call**_
228226
```
@@ -405,10 +403,10 @@ Application.domain.newInstance(accountList, Account.SObjectType);
405403

406404
### The setMock Methods
407405

408-
In every factory class inside the fflib_Application class there is a [setMock method](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_Application.cls#L114). These methods are used to pass in mock/fake versions of your classes for [unit testing purposes](./15-The-Difference-Between-Unit-Tests-and-Integration-Tests). Make sure to leverage this method if you are planning to do unit testing. Leveraging this method eliminates the need to use [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection) in your classes to allow for mocking. There are examples of how to leverage this method in the [Implementing Mock Unit Testing with Apex Mocks](./17-Implementing-Mock-Unit-Tests-with-the-Apex-Mocks-Library) section of this wiki.
406+
In every factory class inside the fflib_Application class there is a [setMock method](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_Application.cls#L114). These methods are used to pass in mock/fake versions of your classes for [unit testing purposes](./15-The-Difference-Between-Unit-Tests-and-Integration-Tests.md). Make sure to leverage this method if you are planning to do unit testing. Leveraging this method eliminates the need to use [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection) in your classes to allow for mocking. There are examples of how to leverage this method in the [Implementing Mock Unit Testing with Apex Mocks](./17-Implementing-Mock-Unit-Tests-with-the-Apex-Mocks-Library.md) section of this wiki.
409407

410408
---
411409

412410
### Next Section
413411

414-
[Part 5: The Unit of Work Pattern](./05-The-Unit-of-Work-Pattern)
412+
[Part 5: The Unit of Work Pattern](./05-The-Unit-of-Work-Pattern.md)

0 commit comments

Comments
 (0)