Нещодавно я розробляв власний API, і з цим інвестував інтерес до дизайну API, я був зацікавлений, як я можу вдосконалити дизайн API.
Один аспект, який з’явився кілька разів, - це (не користувачі мого API, а під час мого спостереження за темою): слід знати лише дивлячись на код, що викликає API, що він робить .
Наприклад, дивіться цю дискусію на GitHub для дискурсного репо, вона виглядає приблизно так:
foo.update_pinned(true, true);
Просто дивлячись на код (не знаючи назви параметрів, документації тощо), ви не можете здогадатися, що він буде робити - що означає 2-й аргумент? Запропоноване вдосконалення - мати щось на кшталт:
foo.pin()
foo.unpin()
foo.pin_globally()
І це все вияснює (я думаю, другий аргумент - чи слід чітко фіксувати глобальний процес), і я згоден у цьому випадку, пізніше це, безумовно, буде вдосконаленням.
Однак я вважаю, що можуть бути випадки, коли методи встановлення різних, але логічно пов'язаних станів було б краще піддаватися як один виклик методу, а не окремий, навіть якщо ви не знаєте, що це робить, просто подивившись на код . (Тож вам доведеться вдатися до перегляду імен параметрів та документації, щоб дізнатись - що особисто я завжди робив би незалежно від того, що, якщо я не знайомий з API).
Наприклад, я виставляю один метод SetVisibility(bool, string, bool)
на FalconPeer і я визнаю, що просто дивлюся на рядок:
falconPeer.SetVisibility(true, "aerw3", true);
Ви б не мали поняття, що це робить. Це встановлення 3 різних значень, які керують "видимістю" falconPeer
в логічному сенсі: приймайте запити на приєднання, лише з паролем та відповідайте на запити на відкриття. Розбиття цього на 3 виклики методу може призвести до того, що користувач API встановить один аспект "видимості", забувши встановити інших, про що я змушую їх думати, лише піддаючи одному методу встановлення всіх аспектів "видимості" . Крім того, коли користувач хоче змінити один аспект, він майже завжди захоче змінити інший аспект і тепер може це зробити за один дзвінок.
setSize(10, 20)
не читайте , як setSize(width=10, height=20)
або random(distribution='gaussian', mean=0.5, deviation=1)
. У мовах із примусовими названими параметрами булеви можуть передавати точно такий же об'єм інформації, як і за допомогою переписок / названих констант, тому вони можуть бути хорошими в API.
update
методі:foo.update(pinned=true, globally=true)
. Або:foo.update_pinned(true, globally=true)
. Таким чином, відповідь на ваше запитання повинна враховувати також мовні особливості, оскільки хороший API для мови X може не бути корисним для мови Y та viceversa.