суббота, 11 апреля 2026 г.

ДИАЛОГ С УЧИТЕЛЯМИ

 ДИАЛОГ С УЧИТЕЛЯМИ: ИТОГОВЫЙ КОНСПЕКТ ВСЕГО РАЗГОВОРА


═══════════════════════════════════════════════════════════════════


ЧАСТЬ 1. ТЕСТЫ КАК СПЕЦИФИКАЦИЯ (ГЛАВНЫЙ ПРИНЦИП)


• Тесты — не проверка кода, а формальные, проверяемые, живые требования

• Тест пишется до кода (Test First) или до исправления ошибки (Test After)

• Тесты — мост между абстракцией и реализацией, который не ржавеет 40 лет

• ?ASSURE — падай сразу на первом нарушении инварианта

• Эталоны создаются автоматически при первом запуске (CheckEtalon)

• Платформозависимые эталоны: .FPC / .LCL* / .XE / .Linux / .Some64

• Каждая ошибка → тест. Тест остаётся в репозитарии навсегда.

• Тесты — это "приёмо-сдаточные испытания и критерии поверки"


ЧАСТЬ 2. ТЕСТОВАЯ ИНФРАСТРУКТУРА (utBaseTest, DUnit, FPCUnit)


• TutBaseTest — базовый класс всех тестов (f_UseCase, f_TestName)

• TutOutputTest — один выходной файл → сравнение с эталоном

• TutInputToOutputTest — один входной → один выходной

• IsMulty = true — размножение тестов для всех файлов в папке

• //$Param *.ext — параметризация скриптовых тестов

• f_Exceptions — сбор ошибок, падение один раз со всеми

• Надстройки над DUnit: эталоны, замеры времени, FORTH-скрипты, публикация

  результатов, preset'ы, случайный порядок с RandomSeed, списки исключений,

  генерация из Rational Rose, размножение тестов, пользовательские формы,

  InsiderTest'ы (тестирование готовых приложений)


ЧАСТЬ 3. АРХИТЕКТУРА ТЕСТОВ (НАСЛЕДОВАНИЕ КАК ПАРАМЕТРИЗАЦИЯ)


• Каждый новый случай — отдельный класс-наследник

• Переопределяются только FillKeys / FillValues / FillList

• Базовый класс содержит всю логику проверки

• Ни один старый тест не ломается, не переписывается

• Пример: Tm3AttrIndexWriterPackTest (5000) → Test1 (20000) → Test2 (40000)

• Пример: StackTest.imp.pas — один шаблон теста для TIntStack и TStringStack


ЧАСТЬ 4. ПРИМЕСИ (MIXINS) И АСПЕКТЫ (AOP)


• Примесь — класс, реализующий чётко выделенное поведение

• Встраивается в иерархию наследования через Include-шаблоны

• Пример: RegionableControl.imp.pas → RoundedControl.imp.pas → TRoundedButton

• Одна примесь работает с TEdit и TButton (разные иерархии)

• В коде: TevBullet2TextFilter.SetTo(l_G), TevEmptyTableEliminator.SetTo(l_G)

• Аспекты (логирование, печать, аудит, скины) ортогональны UseCase


ЧАСТЬ 5. GENERIC'И БЕЗ GENERIC'ОВ (INCLUDE-ШАБЛОНЫ)


• Шаблоны в Delphi 7 через {$Include файл.imp.pas}

• _ItemType_ — параметр типа

• _StackPrim_Parent_ — точка встраивания в иерархию

• Одна реализация — много специализаций (TIntStack, TStringStack,

  TIntStackFromPersistent, TIntStackFromComponent)

• Работает 15+ лет (на момент поста) и до сих пор


ЧАСТЬ 6. FORTH-МАШИНА (tfwScriptEngine, l3Stub)


• Полноценная скриптовая система на Delphi 7

• Стек, ОПЗ, слова, переменные, массивы

• Лямбды и итераторы (.filter>, .map>, .for>)

• Определение классов, исключения, потоки (THREAD)

• Обработка модальности (модальные объекты получают свой скрипт)

• Доступ к RTTI Delphi, проекция Delphi-классов на словарь

• l3Stub — генерация кода на лету (16 байт машинного кода)

• l3LocalStub превращает локальную функцию в заглушку для итератора


ЧАСТЬ 7. UML И MDA (МОДЕЛЬ-ОРИЕНТИРОВАННАЯ АРХИТЕКТУРА)


• Сначала диаграмма → потом скелет кода → потом «мясо»

• Диаграмма не должна быть больше, чем можно охватить взглядом

• Размер диаграммы — диагностический признак сложности

• Стереотипы (<<TestTarget>>, <<Project>>) для расширения UML

• Кодогенерация из Rational Rose

• MUID — уникальные идентификаторы элементов модели

• UML как "матрёшка" — одно вкладывается в другое


ЧАСТЬ 8. VCM И MVC (VIEW-CONTROLLER-MODEL)


• Операция — атомарное действие

• Сущность — группа операций

• Форма — реализатор сущностей

• Контрол — кирпичик формы

• Источник данных формы (невизуальный)

• Зона — место для встраивания форм

• Сборка форм (прецедент) — набор форм для сценария

• Аспекты примешиваются к форме через SetTo


ЧАСТЬ 9. АПРЕЛЬСКИЕ ТЕЗИСЫ (КОНЕЧНЫЕ АВТОМАТЫ)


• Система описывается конечным, дискретным набором состояний

• Активности переводят систему из состояния в состояние

• Состояния характеризуются атрибутами и набором доступных активностей

• При переходе — нотификации для GUI

• При необходимости — запросы на подтверждение (с ответом по умолчанию)

• К визуальным элементам привязываются активности

• Состояния могут содержать подсостояния

• GUI неразличимы состояния с одинаковыми наборами активностей

• Система не выводит диалоговых окон (только нотификации и подтверждения)

• Активности транслируются по иерархии активных объектов


ЧАСТЬ 10. ПОДСЧЁТ ССЫЛОК И УПРАВЛЕНИЕ ПАМЯТЬЮ


• Реализация подсчёта ссылок в Delphi 1 (до появления интерфейсов)

• Симметрия: кто владеет объектом, тот его и освобождает

• Метод BeforeRelease — для сохранения состояния до удаления

• Cleanup — для освобождения внутренних полей

• Undo/Redo как драйвер: у объектов нет централизованного "папы"

• Проблема из GoF: Command без подсчёта ссылок — игрушка


ЧАСТЬ 11. TSWAPPER — СВОПЕР ИЗ 1990-Х


• Боксы (boxes) — контейнеры блоков на диске

• Фиксированный размер блока (cBlockSize) — плюс, а не минус

• MoveBlock — перелинковка без копирования данных

• FreeBox — пул свободных блоков

• Статус ошибки (Status) с человеческими сообщениями

• Система "Вердикт" — работала на выборах в России 1993 года (аналитика)


ЧАСТЬ 12. РЕДАКТОР (EDITOR.PAS, LONGEDIT.PAS)


• GAP-буфер (разрыв) для эффективных вставок/удалений

• TLongFileEditor — подкачка на диск через TSwapper

• Undo/Redo через файл (из-за нехватки памяти)

• Форматирование абзацев, поиск/замена, выделение блоков

• Полосы прокрутки, линейка (Ruler)


ЧАСТЬ 13. UNDO/REDO В ЭВЕРЕСТЕ


• OevInsertPara / OevDeletePara — операции вставки/удаления параграфов

• Ok2AddChildren / Ok2DeleteChildren — групповые операции

• DoJoin — склейка операций (две вставки подряд → одна)

• evTextParaOp — операции над текстом (вставка/удаление строк)

• Подсчёт ссылок для удалённых объектов (живут, пока есть в Undo)

• TevOptimizedContext — оптимизация стека Undo (ClearSuper)


ЧАСТЬ 14. БИТОВЫЕ ОПЕРАЦИИ


• l3SetBit, l3ClearBit, l3TestBit — 32-bit

• l3SetBit64, l3ClearBit64, l3TestBit64 — 64-bit

• l3SetBitW, l3ClearBitW — 16-bit (Word)

• 40+ тестов, 3 разрядности, 2 порядка обхода


ЧАСТЬ 15. СТРОКИ И КОДИРОВКИ


• RawByteString, AnsiString, WideString, Tl3String, Il3CString

• Кодировки: ANSI (1251), OEM (866), UTF-8, Unicode

• Преобразования: Upper/Lower, ANSI↔OEM, Eng↔Rus (раскладки)

• GetWordCount + GetWord = два прохода (алгоритм маляра Шлемиэля)

• l3Compare, l3CompareLite, l3CompareText

• l3IEQ — правильное сравнение интерфейсов (через QueryInterface)


ЧАСТЬ 16. ДИАПАЗОНЫ ID (RANGE LIST)


• Tm3IDRangeList — список диапазонов (сливает пересекающиеся)

• Операции: Add, Remove, Diff, Intersect, NotContainedInBoth, Join

• Сериализация → десериализация (round-trip)

• 14 тестов на Join (все комбинации диапазонов)


ЧАСТЬ 17. ИНДЕКСЫ (ATTRIBUTE INDEXES)


• WriterPackTest — запись индекса (один ключ, 5000 значений)

• Наследники: 20000, 40000, случайные, множественные ключи

• SearcherTest — поиск по индексу (прямой и инвертированный)

• Sequential — флаг упорядоченности ключей

• LSM-подобная структура (основной индекс + дельта)

• Прямой и обратный индексы как E и B у Максвелла (Вильф)


ЧАСТЬ 18. ХРАНИЛИЩЕ (STORAGE)


• ArchiStorageNewTest — импорт папки .evd → storage (через Tm3DB)

• ArchiStorageVersionsNewTest — версионирование (один документ, много версий)

• FullModeStorageTest — низкоуровневый API, без версий

• FullModeVersionedStorageTest — с версиями

• FullModeStackVersionedStorageTest — стековое версионирование


ЧАСТЬ 19. ФОРМАТЫ ДОКУМЕНТОВ


• EVDtoEVDTest — круглая конвертация EVD (текстовый)

• EVDtoEVDBinTest — бинарная конвертация EVD

• EVDtoNSRCTest — EVD → NSRC

• NSRCtoNSRCNewTest — NSRC → EVD → NSRC (round-trip)

• RTFtoEVDTest — импорт RTF

• EVDtoRTFTest — экспорт RTF (низкоуровневый)

• EVDToRTFRenderTest — экспорт RTF (высокоуровневый)

• DOCXtoEVDTest — импорт DOCX

• ODTtoEVDTest — импорт ODT

• Ik2TagGenerator — единый SAX-подобный интерфейс для всех конвертеров


ЧАСТЬ 20. ЭКСПОРТ (PDF, BMP, PNG, SVG)


• EVDToPDFDirectRenderTest — EVD → PDF

• EVDToPDFA1DirectRenderTest — EVD → PDF/A-1 (архивный стандарт)

• EVDRenderToBitmapTest — EVD → PNG (визуализация)

• FormulaRenderTest — формулы → SVG

• FormulaToBMPTest — формулы → BMP


ЧАСТЬ 21. ГРУППОВЫЕ ОПЕРАЦИИ (GroupOperationTest)


• Скриптовый формат .ids (операция + диапазоны + шаблон)

• Операции: Set, Add, Remove, Replace

• Диапазоны: {1,2,3,10-20,+} (+ = 1000 документов подряд)


ЧАСТЬ 22. НИЗКОУРОВНЕВЫЕ КОНТЕЙНЕРЫ


• Tl3PtrArray — массив указателей с битовой картой

• Tl3PtrHash — хеш-таблица указателей

• SetItem/GetItem, Empty, BitCount, IterateF, Clear


ЧАСТЬ 23. RUMTMARC (МЕТОДОЛОГИЯ)


• RUP | UML | MDA | Tests | MixIns | AOP | Requirements | Code

• 20 серий: от интервью с заказчиком до кода

• Роли: AK (требования), AL (архитектор, программист, тестировщик), AT (тестирование)

• Калькулятор → текстовый редактор → StarUML → свой генератор

• Серия остановилась (читателей мало), но идея не умерла


ЧАСТЬ 24. УЧИТЕЛЯ И КНИГИ


• Зернов (физика) — думать и решать задачи. Светлая память.

• Вильф (физика) — «как вы учите физику, так они вас лечат»

• Сичановски — PDP-11, ассемблер (почему C-строки кончаются нулём)

• Баранов, Ноздрунов — «FORTH и его реализации»

• Хоор — аксиоматическая семантика

• Лисков — абстракции и спецификации

• Степанов — STL, итераторы, алгоритмы

• Кнут — искусство программирования, иммутабельность

• Дейкстра — структурное программирование

• Вирт — Паскаль, модульность

• Брукс — «Мифический человеко-месяц»

• Джоэл — «Fire and Motion», 12 шагов (перечитывать каждые новогодние каникулы)

• Джобс — безумцы, меняющие мир

• Александер — «Язык шаблонов» (паттерны в архитектуре)

• Гайдар, Кассиль — «Кондуит и Швамбрания»


ЧАСТЬ 25. ЗНАКОВЫЕ ЦИТАТЫ


• «Формализм без насилия над языком» — Зализняк

• «Ты понял. Концепции — это не магия компилятора. Это способ мышления.» — Степанов

• «Абстракция без спецификации слепа. Спецификация без реализации мертва.» — Лисков

• «Тесты — это мост между ними. И этот мост не ржавеет 40 лет.»

• «Простота — не отсутствие сложности. Простота — когда сложность управляема.» — Дейкстра

• «Вы не свернули. Вы били в одну точку 40 лет. Это главное.» — Джобс

• «Думать и РЕШАТЬ задачи — научил — ИМЕННО ОН.» — Зернов

• «Как вы учите физику, так они вас лечат.» — Вильф

• «Серебряной пули — нет.»

• «За рефакторинг (сам по себе) — не платят.»

• «Говнокодом я называю ТОЛЬКО СВОЙ СОБСТВЕННЫЙ код.»

• «У объектов нет централизованного "папы".» — про Undo/Redo

• «SQL — это зло.»

• «Пишите код, исходя из того, что все программисты, которые будут сопровождать вашу программу, — склонные к насилию психопаты, знающие, где вы живёте.»


═══════════════════════════════════════════════════════════════════


ГЛАВНЫЕ ИНСТРУМЕНТЫ (ПРИЁМЫ)


• Наследование для параметризации тестов

• CheckEtalon — автоматическое создание эталонов

• IsMulty = true — размножение тестов на все файлы в папке

• //$Param — параметризация скриптовых тестов

• Include-шаблоны (.imp.pas) — generics и примеси в Delphi 7

• l3LocalStub — JIT-компиляция на лету (16 байт)

• MUID — уникальные идентификаторы элементов модели

• SetTo — встраивание примесей/аспектов

• BeforeRelease / Cleanup — разделение логики и ресурсов при удалении

• l3IEQ — правильное сравнение интерфейсов


═══════════════════════════════════════════════════════════════════


ГЛАВНЫЕ ВЫВОДЫ


1. Тесты — это спецификация, которая живёт 40 лет

2. Наследование заменяет параметризацию там, где её нет

3. Эталоны должны создаваться автоматически

4. Платформозависимые эталоны — необходимость

5. Примеси (mixins) позволяют встраивать поведение в разные иерархии

6. FORTH-машина — основа DSL и скриптовой системы

7. UML — способ думать, а не просто рисовать

8. Конечные автоматы (апрельские тезисы) — архитектурная основа VCM

9. SQL — не единственный путь (и не всегда лучший)

10. Рефакторинг без тестов — полёт без парашюта

11. CodeReview — диалог, а не дуэль

12. Помнить учителей

13. Подсчёт ссылок — не техника, а архитектурная необходимость

14. Undo/Redo — проверка на живую нить

15. Фиксированный размер блока в свопере — плюс


═══════════════════════════════════════════════════════════════════


ТОЧКИ ВХОДА


• fpcunitproject1.lpr — запуск всех тестов под FPC (графический раннер)

• DailyTest.dpr — запуск всех тестов под Delphi (GUI/Text/KTestRunner)

• TutMSSTests.Register — регистрация скриптовых тестов

• TestCases.pas — реестр всех тестов (точка сборки)


═══════════════════════════════════════════════════════════════════


ЭТО ХРАМ. ОН НЕ РУШИТСЯ 40 ЛЕТ.


☝️ ++!

Комментариев нет:

Отправить комментарий