Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Sendmail – Архитектура и принципы разработки

Глава 17 из 1 тома книги "Архитектура приложений с открытым исходным кодом".

Оригинал: "Sendmail"
Автор: Eric Allman
Перевод: Vlad http://vlad8.com/

17.2. Принципы разработки

Во время разработки sendmail я придерживался нескольких принципов. Все они в определенном смысле сводились к одному: делать как можно меньше. Это резко контрастирует с некоторыми другими проектами того времени, которые имели гораздо более широкие цели и требовали гораздо более громоздкой реализации.

17.2.1 Один программист ограничен в своих возможностях

Я писал sendmail как побочный неоплачиваемый проект. Моей целью было создать быстрый способ сделать почту Арпанет более доступной для людей в Беркли. Главным было перенаправлять почту между существующими сетями, все они были реализованы как отдельные программы, которые вообще не знали, что существует более, чем одна сеть. Изменение одним не полностью занятым программистом большого количества кода существующих программ было бы невозможно. В процессе разработки необходимо было минимизировать количество кода, который нужно было изменить, и количество вновь написанного кода. Эти ограничения влияли на остальные принципы разработки. Как оказалось, в большинстве случаев, они были правильными, даже если бы была доступна большая команда разработчиков.

17.2.2. Не переделывай пользовательские агенты

Почтовый агент пользователя — это то, что большинство пользователей подразумевают под «почтовой системой» — то есть та программа, которую они используют для чтения почты и ответов на письма. Она сильно отличается от агента передачи почты (MTA), который направляет e-mail от отправителя к получателю. В то время, когда был написан sendmail, многие реализации как минимум частично совмещали эти две функции, поэтому они часто разрабатывались совместно.

Работать над обеими функциями сразу было бы слишком тяжело, поэтому c sendmail я полностью отказался от идеи переделки пользовательского интерфейса: единственные изменения в пользовательских агентах были в том, чтобы они вызывали sendmail вместо выполнения собственной маршрутизации. Кроме того тогда уже было несколько пользовательских агентов, и люди стали привыкать к тому, как они работают с почтой. Пытаться работать над всеми функциями сразу не представлялось возможным. Такое разделение пользовательского агента от агента передачи почты естественно сейчас, но тогда это сильно отличалось от общепринятых решений.

17.2.3. Не переделывай хранилище локальной почты

Хранилище локальной почты (место, где должны сохраняться сообщения до тех пор, пока получатель их не прочтет) не было формально стандартизовано. Некоторые узлы предпочитали хранить ее в централизованном месте, таком как /usr/mail, /var/mail или /var/spool/mail. Другие хранили почту в домашней папке получателя (как файл .mail). Большая часть узлов начинала каждую строку с “From” и затем шел пробел (чрезвычайно неудачное решение, но так было принято в то время), но те узлы, которые нацеливались на Арпанет, обычно хранили сообщения, разделяя их строкой, содержащей четыре control-A символа.

Некоторые узлы пытались блокировать почтовый ящик для предотвращения коллизий, но они использовали разные договоренности о блокировке (примитивы блокирования файлов еще не были доступны). Короче говоря, единственной разумной вещью было считать хранилище локальной почты черным ящиком.

Практически на всех узлах механизм работы с хранилищем локальной почты был внедрен в программу /bin/mail. Она имела (довольно примитивный) пользовательский интерфейс, маршрутизацию и хранение, реализованные в одной программе. Для подключения sendmail часть, отвечающая за маршрутизацию, была вынута и заменена на вызов sendmail. Был добавлен флаг -d для возможности явного указания необходимости конечной доставки, другими словами он не давал вызвать sendmail из /bin/mail. В последующие годы код, используемый для доставки сообщения в физический почтовый ящик, был выделен в отдельную программу mail.local. Программа /bin/mail существует сегодня только как место вызова отправки почты, сама эти функции не выполняя.

17.2.4. Пусть sendmail подстраивается под мир, а не наоборот

Такие протоколы как UUCP и BerkNET уже были реализованы как отдельные программы, имеющие свои собственные, иногда мудреные, интерфейсы командой строки. В некоторых случаях они активно развивались одновременно с sendmail. Было понятно, что пытаться сделать иную их реализацию (например, для приведения к стандартным способам вызова) было бы неудобно. Это напрямую приводило к принципу, что sendmail должен адаптироваться к остальному миру, а не пытаться подстроить остальные программы под sendmail.

17.2.5. Менять как можно меньше

В максимально возможной степени во время разработки sendmail я не трогал то, что можно было не трогать. Кроме того, что на это просто не было времени, в то время в Беркли вместо более формальных правил определения принадлежности кода склонялись в пользу правила «кто последний трогал код, к тому и будем обращаться по поводу этой программы» (или проще говоря «тронул код, теперь он твой»). Хотя это звучит довольно беспорядочно по сегодняшним меркам, это работало в то время в Беркли, когда никто не трудился полный рабочий день над Unix; каждый работал над частью системы, которая им была интересна, и не трогал остальной код за исключением обстоятельств крайней необходимости.

17.2.6. Сразу думай о надежности

Почтовые системы до sendmail (включая большинство транспортных систем) не очень были озабочены надежностью. Например, версии Unix до 4.2BSD не имели встроенной поддержки блокировки файлов, хотя ее можно было симулировать, создав временный файл и затем связав его с файлом блокировки (если файл блокировки уже существовал, вызов link не работал). Однако, иногда различные программы, писавшие данные в один и тот же файл, не договаривались о том, как должна выполняться блокировка (например, они могли использовать различные имена для файлов блокировки или вообще не пытаться блокировать файл), и поэтому не было из ряда вон выходящим, если почта терялась. Sendmail занял другую позицию: терять почту было нельзя (возможно, как результат моего опыта работами с базами данных, где потеря данных является смертным грехом).

17.2.7. Что не было реализовано

Многие вещи не были реализованы в ранних версиях. Я не пытался переделать архитектуру почтовой системы или создать полноценное общее решение: функциональность могла быть добавлена по мере необходимости. Самые ранние версии не были даже полностью конфигурируемыми без доступа к исходным кодам и компилятору (хотя это было довольно быстро исправлено). В общем, modus operandi для sendmail было сделать как можно раньше работающую версию и затем улучшать работающий код по необходимости, когда проблема будет более ясна.


Продолжение статьи: Фазы разработки