You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/01-Introduction-to-the-Separation-of-Concerns-Design-Principle.md
+4-6Lines changed: 4 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,5 @@
1
1
---
2
-
layout: default
3
2
title: "1) Introduction to the Separation of Concerns Design Principle"
4
-
nav_order: 2
5
3
---
6
4
7
5
# 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
19
17
20
18
_**The Service Layer:**_
21
19
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)
23
21
24
22
_**The Domain Layer:**_
25
23
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).
27
25
28
26
_**The Selector Layer:**_
29
27
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.
31
29
32
30
---
33
31
@@ -57,4 +55,4 @@ All of the code examples in this repo are examples of SoC in action. You can che
57
55
58
56
### Next Section
59
57
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)
Copy file name to clipboardExpand all lines: docs/02-Introduction-to-the-Apex-Common-Library.md
+4-6Lines changed: 4 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,5 @@
1
1
---
2
-
layout: default
3
2
title: "2) Introduction to the Apex Common Library"
4
-
nav_order: 3
5
3
---
6
4
7
5
# Introduction to the Apex Common Library
@@ -27,9 +25,9 @@ Unfortunately it's not that simple. This library doesn't just automatically do t
27
25
28
26
### The Four Major Classes
29
27
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).
33
31
34
32
---
35
33
@@ -54,4 +52,4 @@ Unfortunately it's not that simple. This library doesn't just automatically do t
54
52
---
55
53
56
54
### 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)
Copy file name to clipboardExpand all lines: docs/03-The-Factory-Method-Pattern.md
+3-5Lines changed: 3 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,5 @@
1
1
---
2
-
layout: default
3
2
title: "3) The Factory Method Pattern"
4
-
nav_order: 4
5
3
---
6
4
7
5
# The Factory Method Pattern
@@ -74,7 +72,7 @@ public with sharing class Task_Service_Impl implements Task_Service_Interface
74
72
}
75
73
```
76
74
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.
78
76
79
77
---
80
78
@@ -86,7 +84,7 @@ Basically it reduces your need to declare concreate class/object types in your c
86
84
87
85
### Where is it used in the Apex Common Library
88
86
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)
90
88
91
89
---
92
90
@@ -100,4 +98,4 @@ The following code example in the repo is an example of how the factory pattern
100
98
101
99
### Next Section
102
100
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)
Copy file name to clipboardExpand all lines: docs/04-The-fflib_Application-Class.md
+5-7Lines changed: 5 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,5 @@
1
1
---
2
-
layout: default
3
2
title: "4) The fflib_Application Class"
4
-
nav_order: 5
5
3
---
6
4
7
5
# The fflib_Application Class
@@ -11,7 +9,7 @@ nav_order: 5
11
9
---
12
10
### What is the fflib_Application class?
13
11
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.
15
13
16
14
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
17
15
@@ -151,7 +149,7 @@ public with sharing class SomeClass{
151
149
}
152
150
```
153
151
---
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)
155
153
156
154
_**newInstance(fflib_SObjectUnitOfWork.IDML dml) Example Method Call**_
157
155
```
@@ -222,7 +220,7 @@ public with sharing class SomeClass{
222
220
}
223
221
```
224
222
---
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)
226
224
227
225
_**newInstance(List<SObjectType> objectTypes, fflib_SObjectUnitOfWork.IDML dml) Example Method Call**_
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.
409
407
410
408
---
411
409
412
410
### Next Section
413
411
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