mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-08-06 09:26:52 +01:00
Triage seed knowledge and document admission test for preview
Remove seven knowledge files whose content is generic software-engineering guidance that a capable LLM already applies without BCQuality present (HTTPS-only, secret-leakage-in-errors, no-credentials-in-URLs, silent security-error swallowing, short transaction scope, HTTP timeouts, StrSubstNo-vs-concatenation). These fail the remedial-knowledge premise and dilute the signal of the preview corpus. Strip the "Seed article — domain stewards should expand" banner from ten files that are ready to showcase (AA0232/AA0233 rules, FindSet read-only semantics, SetLoadFields ordering and usage, CalcFields-in-loops, SecretText end-to-end, DataClassification). The banner remains on files that still need domain-steward refinement. Add a "What belongs here" section to the README stating the admission test: a file exists only if a modern LLM would get something wrong or miss something without it. Gives contributors a concrete yes/no filter before they open a PR.
This commit is contained in:
parent
5a02e6ec93
commit
23184480d0
32 changed files with 14 additions and 424 deletions
|
|
@ -9,8 +9,6 @@ application-area: [all]
|
|||
|
||||
# Add SIFT keys for FlowField aggregations
|
||||
|
||||
> **Seed article.** Converted from an existing performance-review prompt to bootstrap the BCQuality performance corpus. Domain stewards should expand, restructure, and refine as needed.
|
||||
|
||||
## Description
|
||||
|
||||
CodeCop rule AA0232 checks that FlowFields backed by CalcSums or aggregation CalcFormula are supported by a key whose SumIndexFields include the summed field and whose key prefix matches the formula's filter fields. Without a SIFT key the platform falls back to a full aggregation on every read — typically invisible in development and catastrophic in production.
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ application-area: [all]
|
|||
|
||||
# Do not call CalcFields inside loops
|
||||
|
||||
> **Seed article.** Converted from an existing performance-review prompt to bootstrap the BCQuality performance corpus. Domain stewards should expand, restructure, and refine as needed.
|
||||
|
||||
## Description
|
||||
|
||||
CalcFields evaluates one or more FlowFields for the current record by issuing a separate SQL aggregation. Called inside a loop over a record set, it becomes an N+1 problem: one aggregate per row. For any non-trivial set on a ledger-entry-backed FlowField this is orders of magnitude slower than the equivalent batched query.
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ application-area: [all]
|
|||
|
||||
# Do not pair FindFirst, FindLast, or Get with Next
|
||||
|
||||
> **Seed article.** Converted from an existing performance-review prompt to bootstrap the BCQuality performance corpus. Domain stewards should expand, restructure, and refine as needed.
|
||||
|
||||
## Description
|
||||
|
||||
CodeCop rule AA0233 flags loops that start with FindFirst, FindLast, or Get and then call Next. FindFirst and FindLast retrieve a single row and reposition the cursor; calling Next after them forces the platform to re-seek and stream the rest of the set, which is slower than the correct FindSet pattern and signals intent incorrectly to reviewers and the optimizer.
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ application-area: [all]
|
|||
|
||||
# Filter before you find
|
||||
|
||||
> **Seed article.** Converted from an existing performance-review prompt to bootstrap the BCQuality performance corpus. Domain stewards should expand, restructure, and refine as needed.
|
||||
|
||||
## Description
|
||||
|
||||
Every call to FindSet, Find, or FindFirst on an unfiltered record variable scans the entire table. On hot tables (ledger entries, value entries, sales invoice lines) a production dataset can easily be millions of rows, so the cost of forgetting a filter is orders of magnitude worse than the cost of applying one.
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
codeunit 50128 "Perf Sample TxnScope Bad"
|
||||
{
|
||||
procedure ImportCustomers(var Source: List of [Text])
|
||||
var
|
||||
Customer: Record Customer;
|
||||
HttpClient: HttpClient;
|
||||
HttpResponse: HttpResponseMessage;
|
||||
Row: Text;
|
||||
begin
|
||||
foreach Row in Source do begin
|
||||
// external call inside the write transaction
|
||||
HttpClient.Get('https://example.com/validate?row=' + Row, HttpResponse);
|
||||
Customer.Init();
|
||||
// ... populate from Row ...
|
||||
Customer.Insert(true);
|
||||
end;
|
||||
end;
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
codeunit 50123 "Perf Sample TxnScope Good"
|
||||
{
|
||||
procedure ImportCustomers(var Source: List of [Text])
|
||||
var
|
||||
Prepared: Record Customer temporary;
|
||||
Customer: Record Customer;
|
||||
begin
|
||||
// read, validate, and shape outside the transaction
|
||||
PrepareRows(Source, Prepared);
|
||||
|
||||
// transaction starts here: only Insert/Modify calls
|
||||
if Prepared.FindSet() then
|
||||
repeat
|
||||
Customer := Prepared;
|
||||
Customer.Insert(true);
|
||||
until Prepared.Next() = 0;
|
||||
end;
|
||||
|
||||
local procedure PrepareRows(var Source: List of [Text]; var Prepared: Record Customer temporary)
|
||||
begin
|
||||
end;
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
---
|
||||
bc-version: [26..28]
|
||||
domain: performance
|
||||
keywords: [transaction, lock, scope, contention]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Keep transaction scope short
|
||||
|
||||
> **Seed article.** Converted from an existing performance-review prompt to bootstrap the BCQuality performance corpus. Domain stewards should expand, restructure, and refine as needed.
|
||||
|
||||
## Description
|
||||
|
||||
Every write operation runs inside a transaction that holds locks until the transaction ends. Long transactions increase blocking, deadlocks, and timeouts for other sessions. The same work split across narrower transactions typically completes faster under load because it holds locks for less time.
|
||||
|
||||
## Best Practice
|
||||
|
||||
Perform data reads, calculations, and external integrations outside the transaction whenever possible. Enter the writing phase with all inputs computed, execute the minimum set of Insert, Modify, and Delete calls, and exit. If you have a long-running batch, split it into checkpoints at safe boundaries (see avoid-commit-inside-loops).
|
||||
|
||||
See sample: `keep-transaction-scope-short.good.al`.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Opening a transaction, then performing external web-service calls, heavy report runs, or user-facing dialogs while the locks are held, suspends every other session that needs the same rows for as long as the external operation takes.
|
||||
|
||||
See sample: `keep-transaction-scope-short.bad.al`.
|
||||
|
||||
|
|
@ -9,8 +9,6 @@ application-area: [all]
|
|||
|
||||
# Use FindSet in read-only mode by default
|
||||
|
||||
> **Seed article.** Converted from an existing performance-review prompt to bootstrap the BCQuality performance corpus. Domain stewards should expand, restructure, and refine as needed.
|
||||
|
||||
## Description
|
||||
|
||||
FindSet has two modes: FindSet() and FindSet(false) are read-only and take no write lock; FindSet(true) calls LockTable before fetching. Write locks are expensive and hold for the remainder of the transaction, so passing `true` when you do not intend to modify the records increases contention under load.
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ application-area: [all]
|
|||
|
||||
# Use SetLoadFields for partial records
|
||||
|
||||
> **Seed article.** Converted from an existing performance-review prompt to bootstrap the BCQuality performance corpus. Domain stewards should expand, restructure, and refine as needed.
|
||||
|
||||
## Description
|
||||
|
||||
SetLoadFields instructs the platform to hydrate only the listed fields on a record variable. On wide tables, or tables with BLOB or media fields, the difference is substantial: a Sales Invoice Line has dozens of fields and loading all of them for every row of a large set is wasted bandwidth. Primary key fields, SystemId, and system audit fields are always loaded automatically. SetLoadFields works only with FieldClass = Normal; FlowFields and FlowFilters cannot be partial-loaded.
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
codeunit 50137 "Perf Sample StrSubstNo Bad"
|
||||
{
|
||||
procedure CustomerGreeting(var Customer: Record Customer): Text
|
||||
begin
|
||||
exit('Hello, ' + Customer.Name + ' (' + Customer."No." + ')');
|
||||
end;
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
codeunit 50136 "Perf Sample StrSubstNo Good"
|
||||
{
|
||||
procedure CustomerGreeting(var Customer: Record Customer): Text
|
||||
var
|
||||
GreetingLbl: Label 'Hello, %1 (%2)';
|
||||
begin
|
||||
exit(StrSubstNo(GreetingLbl, Customer.Name, Customer."No."));
|
||||
end;
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
---
|
||||
bc-version: [26..28]
|
||||
domain: performance
|
||||
keywords: [strsubstno, string, concatenation, format]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Use StrSubstNo for message formatting
|
||||
|
||||
> **Seed article.** Converted from an existing performance-review prompt to bootstrap the BCQuality performance corpus. Domain stewards should expand, restructure, and refine as needed.
|
||||
|
||||
## Description
|
||||
|
||||
StrSubstNo formats values into a placeholder template in a single call. Manual concatenation with `+` produces a chain of intermediate strings, each allocated and discarded, and mixes formatting rules inconsistently across locales. The performance difference per call is small; repeated inside a tight loop it is noticeable.
|
||||
|
||||
## Best Practice
|
||||
|
||||
Declare the template as a Label (so it can be localized) and format with StrSubstNo. Pass values in the order the placeholders expect; StrSubstNo handles locale-sensitive conversions consistently.
|
||||
|
||||
See sample: `use-strsubstno-for-message-formatting.good.al`.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Building a user-facing string by concatenating record field values with string literals ignores locale rules and allocates more than necessary.
|
||||
|
||||
See sample: `use-strsubstno-for-message-formatting.bad.al`.
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue