mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-10-05 22:56:55 +01:00
Fixes two points from JesperSchulz's review on PR #136. 1. boolean-operators-do-not-short-circuit.md gave one fix — nested if — for and, or, and xor alike. That's only correct for and: nesting if A then if B then Action drops the A-true/B-false case of A or B, silently changing the result. Gives or its own early-exit pattern (if A then exit(true); exit(B)), warns explicitly against applying the and-rewrite to or, and clarifies that xor is not a short-circuit candidate in any language since its result always depends on both operands. Adds an or fixture (IsEligibleForFreeShipping) to both samples so an agent has a concrete pattern to match instead of extrapolating from the and-only examples. 2. case-true-of-for-long-condition-chains.md derived stop-at-first-match for one comma-separated value set from the documentation's guarantee about the first matching value set — plural, i.e. ordering across value sets, which is not the same claim. The good sample's Item.Get / Blocked pair depended on the one the docs don't make. Restructures the sample to only comma-group the three pure, order-independent checks; Get and Blocked keep their own value sets, in order, relying solely on the guarantee that is actually documented. Description and Anti Pattern now state that boundary so it isn't re-collapsed later. Also carries forward a parenthesis fix (not Item.Blocked in the collapsed bad sample) that was made two commits ago but never landed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
41 lines
1.7 KiB
AL
41 lines
1.7 KiB
AL
codeunit 50540 "Perf Sample NoShortCircuit Good"
|
|
{
|
|
procedure ExceedsThreshold(var Thresholds: array[10] of Decimal; Index: Integer; Amount: Decimal): Boolean
|
|
begin
|
|
// 'and' is safe here: both operands are cheap and neither depends on the other.
|
|
if (Index >= 1) and (Index <= ArrayLen(Thresholds)) then
|
|
// The subscript lives in its own if, so it is never evaluated out of range.
|
|
if Amount > Thresholds[Index] then
|
|
exit(true);
|
|
exit(false);
|
|
end;
|
|
|
|
procedure IsBlockedCustomer(CustomerNo: Code[20]): Boolean
|
|
var
|
|
Customer: Record Customer;
|
|
begin
|
|
// The cheap test runs first, and the field is read only after Get succeeded.
|
|
if CustomerNo = '' then
|
|
exit(false);
|
|
if not Customer.Get(CustomerNo) then
|
|
exit(false);
|
|
exit(Customer.Blocked <> Customer.Blocked::" ");
|
|
end;
|
|
|
|
procedure IsEligibleForFreeShipping(SalesHeader: Record "Sales Header"): Boolean
|
|
begin
|
|
// 'or' is unsafe here: nesting would also be wrong, since it would drop the
|
|
// case where the amount alone already qualifies. Exit as soon as the cheap
|
|
// condition already decides the result; the costly lookup runs only on the
|
|
// path where it can still change the outcome.
|
|
if SalesHeader."Amount Including VAT" >= 1000 then
|
|
exit(true);
|
|
exit(HasActiveLoyaltyBenefit(SalesHeader."Sell-to Customer No."));
|
|
end;
|
|
|
|
local procedure HasActiveLoyaltyBenefit(CustomerNo: Code[20]): Boolean
|
|
begin
|
|
// Stands in for a costly check — a webservice call or a large table scan.
|
|
exit(CustomerNo <> '');
|
|
end;
|
|
}
|