Философия проектирования NextPDF
Spec: ISO/IEC 25010 ISO/IEC 25010 Spec: ISO 32000-2 ISO 32000-2 Evidence: Design principle
На этой странице изложены принципы, по которым оценивается каждое решение в API NextPDF. Их намеренно немного: принцип, который вы не можете воспроизвести по памяти, трудно применить под давлением.
Эту страницу стоит прочитать первой. Остальные страницы Insider_ показывают эти принципы в действии на конкретных участках. Здесь они названы явно, чтобы остальная документация обрела смысл.
Почему это важно
Заголовок раздела «Почему это важно»PDF достаточно стар, чтобы опираться на принципы, и достаточно строг, чтобы наказывать за догадки. Подпись охватывает ровно те байты, которые она охватывает. Шрифт либо встроен, либо нет. Архивный профиль либо выдерживает аудит спустя месяцы, либо нет — перед тем, кому нужны доказательства.
Когда входные данные неоднозначны, у библиотеки есть выбор. Она может строить догадки и молчать, а может остановиться и сообщить об этом. Первый вариант выглядит дружелюбнее на демонстрации, но может обернуться инцидентом в продакшене без следов того, что пошло не так. NextPDF выбирает второй. Движок принимает менее обнадёживающее первое впечатление ради поведения, которое можно отстоять. Стандарты качества программного обеспечения называют этот компромисс прямо. Поведение fail-safe — это способность продукта при сбое возвращаться в безопасное состояние, а не продолжать работу в неопределённом состоянии ( Spec: ISO/IEC 25010, §3 ISO/IEC 25010 §3 ).
Если коротко
Заголовок раздела «Если коротко»NextPDF построен на пяти принципах, в порядке приоритета:
- Явное лучше неявного. Если намерение важно, вы заявляете его явно. Движок не выводит из контекста уровень подписи, режим вывода или целевой уровень соответствия.
- Сбой — быстро, громко и рано. Некорректные входные данные отклоняются до записи первого байта, с сообщением, которое называет причину.
- Ошибки — это часть API. Сбои конкретны, типизированы и несут структурированный контекст — спроектированный, а не случайный.
- Границы заявляются, а не обнаруживаются. Каждое утверждение указывает, где оно заканчивается. «Необходимо, но не достаточно» — формулировка, которую NextPDF использует намеренно.
- Ничто не деградирует молча. Движок не возвращает наполовину корректный артефакт, который выглядит завершённым.
Всё остальное — текучий построитель, одноразовый документ, строгая типизация — вытекает из них.
Как NextPDF подходит к этому
Заголовок раздела «Как NextPDF подходит к этому»Эти принципы — не лозунги. Они проявляются как конкретные формы в исходном коде и усиливают друг друга.
В таблице ниже каждый принцип сопоставлен с тем, где он виден в движке и во что обходится его отсутствие.
| Принцип | Как он проявляется в NextPDF | Цена противоположного подхода |
|---|---|---|
| Явное лучше неявного | setSignature(certInfo:, level:) принимает уровень PAdES как обязательный именованный аргумент — уровня “auto” не существует | Документ, подписанный по профилю, которого обязательство не требовало; это обнаруживается при проверке |
| Сбой — быстро и громко | save() отклоняет путь со stream-обёрткой или нулевым байтом до отрисовки; setSignature(), за которым следует save(), выбрасывает исключение, а не создаёт неподписанный файл | Запись с обходом пути или PDF в архиве, который «не подписан, но считается подписанным» |
| Ошибки — это часть API | Одно абстрактное базовое исключение, конкретные типизированные подклассы, каждый из которых предоставляет структурированный getContext() для логов и APM | Обобщённая трассировка стека и долгий день, потраченный на догадки |
| Границы заявляются | Внутрипроцессные проверки соответствия возвращают замечания и прямо сообщают, что вердикт принадлежит независимому валидатору | Вывод «исключения нет, значит, соответствует», который опровергает аудитор |
| Ничто не деградирует молча | Путь архивной отметки времени отказывается вернуть наполовину записанный профиль, вместо того чтобы выдать профиль без обязательного словаря | Профиль долговременной проверки, который на деле таковым не является |
Если прочитать эти принципы вместе, проступает единая позиция: движок скорее даст вам честное «нет», чем уверенное «возможно». Это не пессимизм, а признание того, что PDF часто является юридическим артефактом. Ошибочный юридический артефакт хуже, чем тот, который вовсе не был создан.
Что говорят свидетельства
Заголовок раздела «Что говорят свидетельства»Эта страница представляет собой утверждение уровня Evidence: Design principle : эти принципы — осознанные решения, обоснованные доводами, а не измеренные. Если у принципа есть название во внешней дисциплине, страница опирается на него, чтобы рассуждение не сводилось к внутреннему мнению.
- Позиция «отказать, а не продолжать в неопределённом состоянии» — это свойство качества fail-safe в Spec: ISO/IEC 25010 ISO/IEC 25010 §3: продукт переходит в безопасное состояние при сбое. Отказоустойчивость из того же семейства — это степень, в которой система продолжает вести себя как задумано, несмотря на сбои. NextPDF направляет это усилие на обнаружение и остановку, а не на сокрытие сбоя.
- Позиция «заявить границу до принятия» — это распознаваемость пригодности ( Spec: ISO/IEC 25010, §3.26 ISO/IEC 25010 §3.26 ): способность судить о соответствии по документации и первым впечатлениям.
- Причина, специфичная для PDF, по которой всё это важно, — Spec: ISO 32000-2, §12.8 ISO 32000-2 §12.8 : диапазон байтов подписи защищает ровно те байты, которые он охватывает, и ничего более, поэтому движок, который «услужливо» перезаписывает подписанный документ или строит вокруг него догадки, ничем не помогает.
Отдельные принципы показаны на реальном исходном коде движка на собственных страницах — API, который отказывается угадывать и Ошибки как функция дают Evidence: Code-backed доказательство. Эта страница — о том, «почему»; те страницы — о том, «что».
Практический пример
Заголовок раздела «Практический пример»Эти принципы видны в нескольких строках обычного использования. Вызов подписи заявляет намерение явно. Движок отказывает заранее, а не выдаёт что-то вводящее в заблуждение.
<?php
declare(strict_types=1);
use NextPDF\Core\Document;use NextPDF\Exception\NotImplementedException;use NextPDF\Security\Signature\CertificateInfo;use NextPDF\Security\Signature\SignatureLevel;
$document = Document::createStandalone();$document->setTitle('Service Agreement 2026-0042');$document->addPage();$document->setFont('helvetica', '', 12);$document->cell(0, 10, 'This agreement is configured for a PAdES signature.', newLine: true);
// Explicit beats implicit: the PAdES level is a required, named argument.// There is no inferred or "auto" level.$document->setSignature( certInfo: new CertificateInfo( certificate: $certificatePem, privateKey: $privateKeyPem, ), level: SignatureLevel::PAdES_B_B,);
try { // Fail fast, no silent degradation: rather than emit an UNSIGNED file // that the caller believes setSignature() signed, the high-level path // refuses and names the supported route. $document->save('/srv/output/agreement.pdf');} catch (NotImplementedException $e) { // The message identifies the feature and the follow-up, not a stack // trace: "... is not implemented in this release. <actionable follow-up>" error_log($e->getMessage());}Дело не в механике подписи. В одном фрагменте видны три принципа: намерение заявлено (level:), сбой ранний и именованный, а движок отказывается создавать документ, который ложно сообщил бы о собственном состоянии.
Распространённое заблуждение
Заголовок раздела «Распространённое заблуждение»Самое частое недопонимание — что эти принципы делают NextPDF «сложнее в использовании». Они делают его сложнее использовать неправильно. Обязательный аргумент — это на одно неявное значение по умолчанию меньше, которое могло бы вас удивить. Раннее исключение — это на один повреждённый артефакт в архиве меньше. Трение намеренно помещено туда, где ошибка обходится дёшево — в месте вызова, на этапе разработки, — а не туда, где она дорога: в продакшене, на аудите, в суде.
Второе недопонимание — что «принципиальный» означает «негибкий». Это не так. У движка есть принципы относительно корректности и намерения, а не относительно вашего документа. Вы по-прежнему полностью управляете макетом, содержимым, шрифтами и структурой. Эти принципы — о том, чтобы не угадывать за вас там, где догадка была бы небезопасной.
Ограничения и границы
Заголовок раздела «Ограничения и границы»Эта страница излагает замысел проектирования. Сама по себе она не является спецификацией поведения. Принципы описывают, как принимаются решения, а не гарантии относительно какого-либо отдельного метода. Точный контракт каждого метода находится в справочнике и на собственной странице Insider_ с указанным на ней уровнем свидетельств.
Эти принципы также не являются абсолютными законами физики. Это приоритеты, применяемые осмысленно. Когда два принципа вступают в противоречие (более строгий отказ против более снисходительного значения по умолчанию), решающим становится приведённый выше порядок приоритета. Отдельный модуль всё же может задокументировать обоснованное исключение. Когда это происходит, такое исключение фиксируется, а не подразумевается.
Наконец, «принцип проектирования» здесь является основой свидетельств намеренно. Эта страница приводит доводы. Она не проводит замеров производительности. Утверждения, для подтверждения которых нужны число, тест или пункт стандарта, приводятся на страницах, где находятся эти свидетельства, а не здесь.
Связанная документация
Заголовок раздела «Связанная документация»- API, который отказывается угадывать — принципы явного намерения и быстрого сбоя, показанные на реальном API.
- Ошибки как функция — иерархия типизированных исключений как спроектированная часть API.
- Основы PHP 8.4 — возможности языка, благодаря которым эти принципы можно обеспечивать, а не просто надеяться на них.
Глоссарий
Заголовок раздела «Глоссарий»- Принцип проектирования (уровень свидетельств) — страница, утверждения которой являются осознанными проектными решениями, обоснованными замыслом и релевантными стандартами, а не измеренными бенчмарком или отдельным тестом.
- Fail-safe — свойство качества программного обеспечения: при сбое продукт возвращается в безопасное состояние вместо продолжения работы в неопределённом. Причина, по которой NextPDF отказывает, а не угадывает.
- Fail fast — отклонение некорректных входных данных в наиболее ранней возможной точке, с ясной причиной, вместо того чтобы продолжать и сбоить непредсказуемо позже.
- PAdES — PDF Advanced Electronic Signatures, семейство профилей ETSI для подписания документов PDF (B-B, B-T, B-LT, B-LTA). Здесь расшифровывается при первом упоминании; подробности рассмотрены на страницах о подписании.
- Необходимо, но не достаточно — намеренная формулировка, используемая, когда внутрипроцессная проверка является реальным сигналом, но не вердиктом о соответствии; авторитетное решение принадлежит независимому валидатору.