feat: drawing_fill_title_block — упрочнение по ревью Codex реализации

#3/#6: доступ к графе через RequireStampCell(stamp,columnId) — null-check ячейки
+ единое место валидации (запись и чтение). #4: проверка columnId>0 в helper
(защищает и ReadStampCellAsync). #2/#5: нетранзакционность записи зафиксирована
комментарием (откат при Update()==FALSE спекулятивен, не делаем). RCW — долг v2-2.

Тесты без изменений в числе: 123 unit + 65 integration = 188 зелёных.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 17:25:41 +03:00
parent 742a97177b
commit eaa4a56708
2 changed files with 26 additions and 3 deletions
@@ -1,7 +1,18 @@
# Дизайн: основная надпись чертежа (drawing_fill_title_block) через API7
**Дата:** 2026-05-27
**Статус:** реализовано и проверено (4 интеграционных + 7 unit, всего 188); ревью Codex спека учтено
**Статус:** реализовано и проверено (4 интеграционных + 7 unit, всего 188); ревью Codex спека и реализации учтено
## Правки по ревью реализации Codex
- **null-check ячейки** (#3): доступ к графе через `RequireStampCell(stamp, columnId)` — проверяет
`columnId > 0` и `Text[columnId] != null` с диагностикой; используется в записи и чтении (единое
место валидации, #6).
- **`columnId <= 0`** (#4): валидируется в `RequireStampCell` (защищает и `ReadStampCellAsync`).
- **Нетранзакционность** (#2/#5): записываем все графы, затем один `Update()`; при `Update()==FALSE`
откат старых значений не делаем — зафиксировано комментарием как осознанное поведение (откат
спекулятивен, сценарий невоспроизводим).
- **RCW** — осознанный долг (v2-2), точечный release не вводим.
## Находка спайка: `Str` ПЕРЕЗАПИСЫВАЕТ (Clear не нужен)
+14 -2
View File
@@ -46,8 +46,11 @@ public sealed class DrawingService
throw new ArgumentException("Укажите хотя бы одно поле основной надписи (designation/name/material).");
var stamp = RequireActiveStamp();
// Нетранзакционно: все графы записываются, затем один Update() фиксирует. При Update()==FALSE
// (на практике не воспроизводится) откат старых значений не делаем — он спекулятивен (Str уже
// на in-memory объектах графы, повторный Update мог бы тоже упасть); сообщаем об ошибке.
foreach (var (columnId, text) in fields)
stamp.Text[columnId].Str = text; // Str замещает содержимое (Clear не нужен)
RequireStampCell(stamp, columnId).Str = text; // Str замещает содержимое (Clear не нужен)
if (!stamp.Update())
throw new InvalidOperationException("IStamp.Update вернул FALSE — основная надпись не обновлена.");
return fields.Count;
@@ -58,9 +61,18 @@ public sealed class DrawingService
=> _dispatcher.InvokeAsync(() =>
{
var stamp = RequireActiveStamp();
return stamp.Text[columnId]?.Str ?? string.Empty;
return RequireStampCell(stamp, columnId).Str ?? string.Empty;
}, ct);
/// <summary>Получить графу основной надписи по номеру с диагностикой (номер &gt; 0, ячейка != null).</summary>
private static IText RequireStampCell(IStamp stamp, int columnId)
{
if (columnId <= 0)
throw new ArgumentOutOfRangeException(nameof(columnId), "Номер графы основной надписи должен быть > 0.");
return stamp.Text[columnId]
?? throw new InvalidOperationException($"Графа {columnId} основной надписи недоступна (Text[{columnId}] == null).");
}
private IStamp RequireActiveStamp()
{
var doc2d = RequireActiveDrawing();