Developer Digest Vol. 500: Not-so-Random Thoughts on Simplifying AL Code Development

Calling Business Logic in a Codeunit from a Rec Variable
The other day a colleague and I differed in our opinion of calling business logic in a codeunit from a Record variable rather than calling the business logic from some other place, a Page for instance.
As he was debugging my code, he didn’t like that I had a Rec.DoSomething() which then calls MyCodeUnit.DoSomething(Rec), where the business logic resides.
So, I thought about it and came to some conclusions:
Encapsulation with Flexibility
- By adding a method to Rec like Rec.DoSomething(), you provide a convenient way for other parts of the system to trigger the behavior directly on the Rec variable.
- Internally, calling MyCodeUnit.DoSomething(Rec) keeps the business logic centralized and decoupled from the record itself, promoting better separation of concerns.
Reusability
- The business logic resides in the codeunit, making it reusable across different contexts or even other record types.
- The method on the Rec serves as a convenient wrapper, making it easy to use without requiring every caller to know about the codeunit.
Maintainability
- Since the core logic is in the codeunit, any changes to the logic require updates only in the codeunit, reducing the risk of inconsistencies and making the system easier to maintain.
- The method on the Rec can remain simple, just passing Rec to the codeunit.
Testability
- You can still easily test the logic in MyCodeUnit.DoSomething(Rec) independently, which is particularly useful for unit testing.
- The method on Rec can be tested as part of Integration and Unit tests to ensure it correctly delegates to the codeunit.
Readability and Usability
- The method on the Rec (Rec.DoSomething()) makes the code more readable and easier to use from the perspective of the Rec API consumers.
- It hides the complexity of needing to know which codeunit to call, simplifying the interface for developers.
Code Example
Here’s how you would implement this in AL:
Somewhere in code:
Var SalesHeader: Record “Sales Header”;
Begin
SalesHeader.DoSomething();
End
table 36 “Sales Header”
{
procedure DoSomething()
var
MyCodeUnit: Codeunit 50100;
begin
MyCodeUnit.DoSomething(Rec);
end;
}
codeunit 50100 MyCodeUnit
{
procedure DoSomething(Rec: Record “Sales Header”)
begin
// Business logic here
end;
}
Why use this technique?
This simple example shows how this pattern can be used and is a quite common practice by AL developers. In a real customer solution, you would see dozens of examples of this pattern with much more complexity. You can see that by calling the function from the Record variable, the developer doesn’t need to know about the complexity that exists in the business logic or even care if a codeunit is involved.
Using this approach is often a best practice in Business Central development. It combines the strengths of encapsulation and separation of concerns, leading to a codebase that is easier to understand, test, maintain, and extend.
Don’t miss these upcoming events
- Jon will present on “Automated Testing in the Wild” at Directions for Partners: Days of Knowledge Americas 2024 in Atlanta, Georgia, September 12-14, 2024.
- Be sure to join us at Community Summit North America 2024 in San Antonio, Texas, October 13-17, 2024.
Trending Posts
Stay Informed
Choose Your Preferences
"*required" indicates required fields