Удобство?
(В оригинале Convenience Is not an -ility)
О важности проектирования хорошего API уже было сказано очень много. Хороший API трудно сделать с первого раза и еще труднее изменить его потом. Большинство программистов выучили, что хороший API соответствует уровням абстракции, демонстрирует логичность и симметрию, а также формирует словарь выразительного языка. Увы, одно знание о принципах не приводит к желаемому результату.
Вместо чтения возвышенных проповедей я хочу лишь обратить внимание на одну стратегию API, которую я открываю снова и снова – аргумент удобства. Обычно все начинается с догадки вроде:
- Я не хочу, чтобы другим классам приходилось делать два вызова для того, чтобы сделать вот это.
- Зачем мне нужна еще одна функция, если эта уже делает почти то же самое. Я лучше добавлю туда еще один параметр-переключатель.
- Смотрите, все просто. Если второй параметр заканчивается на .txt, то функция автоматически решит, что первый параметр – это имя файла, и вторую функцию можно не делать.
Однако несмотря на благие намерения, это приводит к снижению читабельности кода, использующего такой API. Вызов такого метода:
parser.processNodes(text, false);
практически бессмысленен без знания подробностей реализации или чтения документации. И скорее всего, метод был написан для удобства его писавшего в противоположность удобству использующего. На самом деле фразу «Я не хочу, чтобы надо было вызывать два метода» следует читать как «Я не хотел писать два отдельных метода». Ничего радикально неправильного в удобстве нет, если говорить об удобстве как о противоядии к монотонности, неуклюжести или неповоротливости. Однако, если чуть глубже копнуть, то противоядием к перечисленным симптомам будет эффективность, логичность и элегантность, а вовсе не удобство. API предназначен для скрытия нижележащей сложности, и вполне логично ожидать, что проектирование хорошего API потребует определенных усилий. Написать один большой метод будет гораздо удобнее, чем продумать адекватный набор операций, но вот будет ли этот метод более удобен в использовании?
Сравнение API с языком может привести нас к лучшему пониманию того, какое решение следует принять. API должен предоставить словарь, дающий возможность вышележащему уровню задавать нужные вопросы и получать ответы. Необязательно, чтобы для каждого вопроса использовалось единственное слово. Разнообразие словаря может позволять использовать различия в значениях. Так, мы скорее предпочтем метод run вместо метода walk(true), даже если они будут полностью эквивалентными. Последовательный и хорошо продуманный словарь, используемый для API, сделает код следующего уровня более выразительным и понятным. Еще более важно, что если словарь можно будет комбинировать, то другие программисты смогут использовать API так, как вы и не подозревали – на самом деле отличное удобство для использования. Когда в следующий раз захотите объединить несколько вещей в один метод, вспомните, что в языке нет слов вроде УбратьВКомнатеИСделатьУроки, даже если вам такое слово кажется удобным для обозначения часто используемого действия.
Автор оригинала - Gregor Hohpe