Comments 41
function login(mode) {
if (mode === "account") {
loginWithPassword();
} else if (mode === "email") {
loginWithEmail();
} else if (mode === "mobile") {
loginWithMobile();
} else if (mode === "google") {
loginWithGoogle();
} else if (mode === "facebook") {
loginWithFacebook();
} else if (mode === "apple") {
loginWithApple();
} else if (mode === "twitter") {
loginWithTwitter();
}
}
Со временем обнаружится, что эту функцию все труднее поддерживать.
Мне вот интересно в чем может быть сложность? Даже если ещё 10 условий добавить или больше, хоть 100. Тут же всё просто как 2х2, если это, то вот это, написано черным по белому.
Понятное дело можно более аккуратно это расписать, но сути это не меняет, сложности то нет на самом деле.
const modes = {
account: loginWithPassword,
email: loginWithEmail,
mobile: loginWithMobile,
// ... и так до бесконечности
}
function login(mode) {
const method = modes[mode];
if (method) {
method();
} else {
throw new Error('Политика аутентификации не установлена!');
}
}
Это как один из вариантов, где так же сложности 0 и при добавлении новых политик сложности так и останется 0.
Просто для решения такой простецкой задачи прибегать к целому паттерну да ещё и с названием стратегия, а выгода то в чем?)
Если код используется в одном месте, то так проще. Если нужно переиспользовать, причём с разными настройками по месту, то вариант со стратегиями более удобен.
Если нужно переиспользовать, причём с разными настройками по месту, то вариант со стратегиями более удобен.
А конкретный пример с кодом пожалуйста можно? Чтобы было видно наглядно как простые варианты пасуют, а вариант со стратегией удобен получается.
Можно добавлять/заменять/настраивать стратегии по месту. При этом авторы аутентификатора и самих стратегий не зависят друг от друга и работают в рамках контракта (интерфейс Strategy)
//web
if (isRU) {
auth.use('fb', new FBStrategy({...proxySettings}));
auth.use('vk', new VKStrategy());
}
//desktop
if (isDesktop) {
auth.use('account', new LDAPStrategy({dc: 'dc.acme.com'}));
}
//mobile
if (isMobile) {
auth.use('account', new AndroidAccountsStrategy());
}
Собственно, в статье есть ссылка на pasport.js, как пример, для которого написано куча стратегий. Можно комбинировать их под свои потребности.
Так вы привели такой же банальный пример, который не является какой то сложностью и т.п.
const modes = new Map();
//web
if (isRU) {
modes.set('fb', FB({...proxySettings}))
modes.set('vk', VK());
}
//desktop
if (isDesktop) {
modes.set('account', LDAP({dc: 'dc.acme.com'}));
}
//mobile
if (isMobile) {
modes.set('account', AndroidAccounts());
}
function login(mode) {
const method = modes.get(modes);
if (method) {
method();
} else {
throw new Error('Политика аутентификации не установлена!');
}
}
В чем разница-то не пойму? Условия есть? Есть. Конфиг есть? Есть. И в чем удобство именно применения паттерна стратегия в данном случае?
И Вы только что реализовали паттерн "стратегия", только другими инструментами
Хотя, нет, не совсем
Я привёл, условно, три куска кода из трёх разных проектов. Их пишут разные команды. Сам аутентификатор пилит четвертая.
Получается конкретно на месте у меня нет функции login. Есть экземпляр Auth, там могут быть даже какие-то предустановленные стратегии. Я его могу как есть использовать, + могу что-то своё добавить.
И вы только что реализовали паттерн "стратегия", только другими инструментами
Да это не инструменты, это вообще просто самая стандартная и банальная реализация)
Именно так. И паттерн - это абстракция для самых стандартных и банальных реализаций. Как это часто бывает с абстракциями, под одну абстракцию подходит сразу много разных версий конкретики. Если у вас есть переключатель и куча объектов, способных через этот переключатель выбрать себе какой-нибудь образ действий в каком-то случае, это - паттерн стратегия. Если у вас есть объект, способный дёргать скопом какую-то группу, куда можно вписываться, это - паттерн подписка. И он, очевидно, не совсем близок стратегии. При этом и тот, и этот паттерны абсолютно типичны.
Пример аутентификации хорошо поясняет устройство паттерна, но аутентификация как таковая в каждом отдельном случае требует мало строчек. Представьте себе более сложные действия, с внутренней сложной логикой каждое. Причём с разной сложной внутренней логикой - чтобы от чтения всех подряд зарябило в глазах.
Паттерн "стратегия" позволяет выносить разные способы действия в отдельные файлы, и старые способы уже не трогать, когда добавляете новый.
Во-первых, так меньше риска что-то сломать.
Во-вторых, сборщик может разбить итоговый код на чанки, а сервер может не отдавать на каждый запрос все эти чанки сразу - они не везде могут быть нужны в полном составе. Что, в свою очередь, ускоряет загрузку.
Представьте себе более сложные действия, с внутренней сложной логикой каждое.
Круто, а каким боком тут помогает стратегия?))) Мы уже выяснили что она ничего не дает и ни на что не влияет. Только носит "гордое" имя паттерн) Прям не стесняйтесь, покажите это в коде. Я хочу наконец-то выяснить где ее применять и применима ли она на самом деле вообще где-то.
Паттерн "стратегия" позволяет выносить разные способы действия в отдельные файлы, и старые способы уже не трогать, когда добавляете новый.
А if'ы нельзя разбить на отдельные файлы?
Во-первых, так меньше риска что-то сломать.
Не вижу связи с реальностью. Вот когда все написано топорно, то риска точно меньше, если это, то это, если так, то вот эдак.
Во-вторых, сборщик может разбить итоговый код на чанки, а сервер может не отдавать на каждый запрос все эти чанки сразу - они не везде могут быть нужны в полном составе. Что, в свою очередь, ускоряет загрузку.
А на чанки только паттерн стратегия разбивается, да? import('lalla').then это всё обман, и работает только при условии что вы сборщику в разговоре по душам обмолвились о том, что вы тут не просто так, а паттерны используете, да ещё и не абы какие, а стратегию.
Только носит "гордое" имя паттерн) Прям не стесняйтесь, покажите это в коде.
Похоже, код ни при чём.
Похоже, проблема в транслитерированном англоязычном термине "паттерн". Который на английском ни разу не гордый, а как раз в хвост и в гриву используется, в разных причём отраслях, для выражения того факта, что есть различные способы что-то сделать.
Если бы перевели словарно, было бы по-русски "способ" или "вариант выполнения задачи". Проблема со словарными переводами в том, что они не точные. В итоге часто термины не переводятся, а транслитерируются - переписываются в других литерах, в другом алфавите, но остаются на слух как были.
Ельцин однажды посетовал: "зачем нам зарубежное слово ваучер, когда есть наше, приватизационный чек". Возможно, второй вариант казался ему отечественнее, поскольку там слово "чек", и "чек" было словом привычным, их же и до того "пробивали" в магазине. "Выбивали на кассе".
Паттерны есть ещё, например, поведенческие. Это типичный термин для психологии - для русскоязычной тоже.
Так где главный ответ на вопрос, в каком случае стратегия явно лучше if'ов? Ответ в виде кода пожалуйста
Ни в каком. Ни в каком случае ничто одно не лучше другого чего бы то ни было явно. Это личные предпочтения, как кому проще думать.
Ответ в виде кода пожалуйста
Вам проще думать на уровне кода.
Но выше @BerkutEagleпривёл пример, когда на уровне кода вообще не выйдет - код в разных стратегиях не просто разный, а на разных языках, и пишется в разных командах. При этом команды между собой договаривались, что делать, именно на уровне паттернов.
Мне тоже проще думать на уровне паттернов. Мне проще так планировать мою работу с проектом.
Хотя ладно, попробую выдумать что-то, где уровень кода будет уж очень запутанным, если сразу за него взяться, без паттернов.
Давайте запилим игру "зоопарк". В зоопарк подселяют животных, разные виды. Каждый из этих видов по-своему взаимодействует с посетителем: кто-то убегает вглубь вольера, кто-то начинает орать, сидя на месте. Кто-то подходит и что-нибудь ест из рук. Ну и засада в том, что мы не знаем, кто ещё там появится - какие ещё животные понадобятся со временем.
Срабатывать это должно каждый раз при проходе посетителя мимо вольера с данным животным.
Как это можно реализовывать?
Например, иф-елсами. Вот есть событие "подошёл посетитель". Дальше каждый класс каждого животного имеет свой совершенно отдельный индивидуальный метод, что ему делать.
Реализация так себе, поскольку одно и то же мы будем использовать в разных местах. Вглубь вольера могут убегать сразу несколько видов, в остальном существенно различающихся. Поэтому мы не можем наследовать их от одного класса, но можем в них вставить что-то, что будет вынесено в отдельный файл как реакция на событие "подошёл посетитель".
В итоге мы получаем несколько файлов (классов, функций) с разными типами реагирования на это событие. И каждому очередному виду зверей вставляем какой-то вариант из имеющихся, или дописываем новый вариант.
Естественно, всё это можно писать просто на уровне кода. Можно просто рефакторингом прийти к нескольким функциям для реагирования на "подошёл посетитель".
Но некоторым людям - не всем, но некоторым - проще заранее подумать об этом как "вот, там будет событие Подошёл посетитель, и способы реагирования вынесем-ка в стратегию".
Будет у нас отдельная папка "стратегии взаимодействия с посетителем".
Ещё будет, скажем, отдельная совершенно "стратегии взаимодействия с сотрудниками зоопарка". Распределение может быть вообще другим. Кто-то, кто убегает от посетителя, может и от сотрудника убегать. Кто-то может от посетителя убегать, но любить сотрудника. И др.
Т.е., очень полезно заготовить возможность подписывать наших животных на переключатели разных типов стратегий. Вот заяц, подписываем его на стратегию убегания от посетителя и на стратегию убегания от сотрудника. Вот лиса, подписываем её на стратегию убегания от посетителя и на стратегию интереса к сотруднику. У стратегий взаимодействия с посетителем свой переключатель, у стратегий взаимодействия с сотрудником - свой.
И да, всё это можно продумать и выполнить без всяких паттернов.
Вот вы сами же расписали то, что со стратегией эта задача реализуется более сложно, чем так сказать гибким методом и индивидуальным подходом. Применять инструменты/паттерны и т.д и т.п, нужно для упрощения жизни, а не для усложнения. Каждую задачу эффективно решать индивидуальным подходом, а не применять паттерн ради паттерна(в вашем случае вы это выдаете за серебряную пулю). Если говорить на языке аббревиатур, то для меня само собой разумеющиеся и первостепенные вещи это "KISS (Keep it simple, stupid), YAGNI (You aren't gonna need it), Чем меньше, тем лучше (Less is more) ". Всё остальное не имеет значения и без разницы как оно называется, стратегия, квест, стрелялка, я всегда делаю именно так, как удобно, как очевидно, код должен легко читаться и быть понятным сверху вниз, слева направо.
При этом команды между собой договаривались, что делать, именно на уровне паттернов.
Вот прям так да? Прям на уровне паттернов? Т.е. не словами, что и как мы делаем, а так: Вася ты делай стратегию, Петя ты делай Наблюдателя и т.п. так получается?
Мне тоже проще думать на уровне паттернов. Мне проще так планировать мою работу с проектом.
Это вы так пытаетесь возвысить себя над теми кто думает как лучше сделать, а не паттернами?)
И самое главное, в чем разница в if'ами? Куда не глянь, так это одно и то же, просто назвали стратегией.
Вот вы сами же расписали то, что со стратегией эта задача реализуется более сложно, чем так сказать гибким методом и индивидуальным подходом.
Нет. Я не писала, что это "более сложная" реализация. Она другая. Она, например, позволяет вообще ни разу не упоминать код. Даже язык, на котором это будет написано, не упоминать.
Можете ли вы в моём комментарии выше выяснить, это игра на питоне, на джаваскрипте или ещё на чём-то? Нет. Потому что на чём угодно.
Вот прям так да? Прям на уровне паттернов? Т.е. не словами, что и как мы делаем, а так: Вася ты делай стратегию, Петя ты делай Наблюдателя и т.п. так получается?
Да, именно так. Хотя, конечно, не в одно слово, а с конкретизацией: стратегия чего именно, и в каких формах мы уже видим её ("выделяем реакцию на посетителя в стратегию, и заготавливаем три первых версии: убежать вглубь вольера, сидеть на месте орать, подойти к посетителю").
Мне тоже проще думать на уровне паттернов. Мне проще так планировать мою работу с проектом.
Это вы так пытаетесь возвысить себя над теми кто думает как лучше сделать, а не паттернами?)
?
Все думают, как лучше сделать. И некоторым проще так (лучше) сделать именно с помощью паттернов. Я себя чувствую с паттернами не лучше, а свободнее.
И самое главное, в чем разница в if'ами? Куда не глянь, так это одно и то же, просто назвали стратегией.
Бывают ифы, бывают объекты с ключами. В РНР это будут ассоциативные массивы, а не объекты. Ну или те же ифы, свитчи. Ещё - вполне сумасшедший пример, ни разу ещё так не делала, но почему бы и нет - класс вы навешиваете из ваниллы, но анимация происходит уже на уровне стилей. И есть несколько классов с разными анимациями.
______________________
Сказать по правде, мне надоел этот разговор, он бессмысленный. Я пишу "как я стала свободнее, познакомившись с паттернами". Вы отвечаете "вы стремитесь возвыситься". Я про паттерны, вы про самолюбие. Причём про самолюбие вы под статьёй про паттерны.
Лучше бы наоборот, но я такого не видела: кто-то пишет статейку про самолюбие (если совсем детально копировать, то переводит с английского статью из цикла про самолюбие), а кто-то приходит там в комментарии и начинает последовательно в одну точку долбить: "что вы мол про самолюбие про какое-то там, вот же паттерны!.." "Что вы пытаетесь самолюбие навязать другим людям с паттернами!!!"
"Да упаси бог вам что-то навязывать," - ответят вам. "Просто если вы в курсе, что у вас с самолюбием, вам проще себя понимать. И дальше проще лишний раз в лужу не плюхаться."
Вы так и ответили на вопрос, чем стратегия отличается от if'ов или obj[key].method() ? Судя по вашим рассуждениям вы точно это знаете, я вот нет и хочу узнать. А вам жалко ответить
чем стратегия отличается от if'ов или obj[key].method()
Ничем. Вернее, сам вопрос поставлен примерно так же, как, например, "чем лисы отличаются от млекопитающих"
лисы от млекопитающих не отличаются - лисы являются вариантом млекопитающих
есть ещё дофига млекопитающих, они не лисы
есть ещё варианты помимо млекопитающих, например мухи. Хотя скорее не мухи, а насекомые, или членистоногие, если мы хотим выдерживать сравнения на одном каком-то родственном уровне абстракции
Добавлю, кстати, что классификация в биологии возникла позже, чем описания отдельных видов. И так же с паттернами - паттерны были вычленены из уже привычных способов писать код. И как вообще и что вычленять - отдельная тема, там не всё гладко. Есть другие системы паттернов, помимо классического набора "банды четырёх". А та же "банда четырёх" старательно упирает на то, что предложили они только некоторый набор паттернов, а не исчерпывающую систему.
Ничем.
Ну вот, значит я правильно думаю. Спасибо за подтверждение.
Ничем на уровне кода. Как лисы на уровне лис - это не столько млекопитающие, сколько лисы. Глупо в беседе конкретно о лисах думать о млекопитающих.
Однако если вы, скажем, исследуете лекарства, вам может быть полезно сравнить лису с кем-то ещё. И часто полезнее её сравнивать с зайцем, а не с лягушкой.
Т.е., если вы в принципе только по лисам, вам может быть вообще ни разу в жизни не важно, относится ли она к царству грибов или нет. Это всё время конкретные лисы, конкретный набор иф-элс.
Но если у вас зоопарк или биолаборатория, вам уже требуются абстракции, классифицирующие лис и ещё кого-то в один общий кластер.
Если вы пишете на одном языке программу, которую не планируется развивать во все стороны, причём временами в непредсказуемые все стороны, конечно имеет смысл не заморачиваться и кодить сразу.
Я на днях написала плагин для хрома для локального бана в комментариях - см. у меня в статье "Habracleaner, плагин для Chrome". Ну и там джаваскриптовых ровно два файла - один занят формой вверху страницы, другой - комментариями. И там не то, что паттернами не пахнет, там вообще лапшекод практически. Ну потому что была задача конкретная, примитивная, без каких-либо планов по её расширению.
Т.е., никто не стремится пихать всюду паттерны ради паттернов.
Если вы пишете на одном языке программу, которую не планируется развивать во все стороны, причём временами в непредсказуемые все стороны, конечно имеет смысл не заморачиваться и кодить сразу.
Т.е. программу которую можно расширять и поддерживать можно писать только когда ты думаешь паттернами, стратегиями, стрелялкам, квестами, а не просто думаешь как сделать хорошо, просто, понятно, очевидно и надежно так?
Т.е. программу которую можно расширять и поддерживать можно писать только когда...
Найдите, пожалуйста, у меня слово "только"?
Если вам даже на многослойных многокомандных проектах с поддержкой на много лет удобнее без чего бы то ни было кроме KISS, DRY и YAGNI, ну так и флаг вам в руки.
А для чего вам, кстати, все эти KISS и DRY, почему бы не просто сосредоточиться на читаемости, расширяемости и простоте? (сарказм, но всё таки)
А для чего вам, кстати, все эти KISS и DRY, почему бы не просто сосредоточиться на читаемости, расширяемости и простоте?
KISS, DRY и YAGNI это и есть про читаемость, очевидность и простоту. Но я не применяю KISS, DRY и YAGNI преднамеренно, просто эти определения подходят под то, как я пишу код. А я пишу его думая своей головой, а не применяю паттерны чтобы утешить чье-то эго и казаться "умнее" за счет этого.
Если вам даже на многослойных многокомандных проектах с поддержкой на много лет удобнее без чего бы то ни было кроме KISS, DRY и YAGNI, ну так и флаг вам в руки.
Ну вот как бы да, отсюда вопрос, зачем думать паттернами и преднамеренно их применять, если можно делать ровно тоже самое и даже лучше без этого?
Но я не применяю ХХХ преднамеренно, просто эти определения подходят под то, как я пишу код
(это про паттерны и про меня)
если можно делать ровно тоже самое и даже лучше без этого
А тут вопрос. Есть ли у вас реально возможность сравнивать? Есть ли у вас возможность сравнить, как вы сами пишете с паттернами и без? Мне пока что кажется, что паттерны как таковые для вас выглядят гиперсложно, и вы выдумываете причины, чтобы от них держаться подальше гордо. Не просто так держаться от них подальше, а именно агрессивно держаться. Скажем, прийти под статью о паттернах и написать "какая дрянь эта ваша заливная рыба".
Т.е., пока что мне слабо верится, что вы уже написали что-то на паттернах, и постфактум видите, что нет, это вам не дало ни черта, кроме будничных утренних драм.
Если бы вам было пофигу до всех этих паттернов, треда бы вообще не было, прямо с первого же вашего комментария. Вы бы сюда не зашли бы просто.
Я просто называю вещи своими именами. Не Стратегия, а if'ы, не Наблюдатель, а pub/sub или EventEmitter, не Функция высшего порядка, а функция обертка, и т.д. и т.п. Это резко снижает значимость оперирования этими терминами, потому что за ними ничего особенного не стоит, вот вы и беситесь))
Я не бешусь, я офигеваю и ржу. Это другое совсем.
Возможно, вы так настойчивы как раз от непонимания реальной реакции паттернофилов на ваши комментарии. Люди, перестающие отвечать, не "поняли вашу правоту", а просто махнули рукой. У них есть другие дела, они проекты ваяют.
А я ещё преподаю. И для меня это любопытная педагогическая ситуация: попробовать так и эдак взаимодействовать с человеком, не просто не шибко владеющим каким-то методом, но громогласно (см. первый ваш комментарий в треде) его обесценивающим.
Вернее, конечно, конкретно здесь это - не педагогическая ситуация. Т.е., вы сюда не учиться пришли, тем более - не учиться у меня лично. Опять же, я не беру у вас денег, поэтому никаких обязательств за итоговое прояснение темы лично для вас я на себя не беру.
Так я же говорю:
Я просто называю вещи своими именами. Не Стратегия, а if'ы, не Наблюдатель, а pub/sub или EventEmitter, не Функция высшего порядка, а функция обертка, и т.д. и т.п. Это резко снижает значимость оперирования этими терминами, потому что за ними ничего особенного не стоит
А вы:
Я не бешусь, я офигеваю и ржу. Это другое совсем.
И дальше всё к теме не относится. Вы избегаете неудобных предложений и вопросов как и делали этого выше.
Не Стратегия, а if'ы, не Наблюдатель, а pub/sub или EventEmitter, не Функция высшего порядка, а функция обертка, и т.д. и т.п.
Это не так?
Люди, перестающие отвечать, не "поняли вашу правоту", а просто махнули рукой.
Нет, просто факту они поняли, что Стратегия это ничто иное как if'ы или obj[key].exec(). А вы это уже признали, но упорно пытаетесь возвысить этот термин над if'ами всё равно, только не ясно почему?)
Дальше всё именно что относится к теме. И я раз за разом отвечаю на ваши вопросы. Просто вы не прочитываете ответы. То ли вы не понимаете эти ответы, уже прочитав, то ли даже не смотрите, что там написано.
У меня были ученики, у которых проблемы с математикой были связаны с чтением. Люди просто не могли прочитать предложение с запятой. Либо на запятой останавливались, либо прочитывали до конца, но не понимали, что оно значит в целом.
У вас то же самое. То ли не можете прочитать, то ли прочитываете, но не понимаете, то ли даже не пробуете вчитыватся.
Тут, разумеется, стоило бы уточнить, что паттерны как таковые - тема довольно сложная. При изучении паттерны не очевидны, естественно. При применении очевидны, когда к ним привыкнешь. Но для начала надо довольно много потратить сил и времени при их изучении.
Возможно, как раз поэтому вы не прочитываете в моих ответах 90% сути. Вы глубочайше сосредоточены на поиске подтверждений того, что паттерны не нужны. Поэтому, скажем, в моём ответе "ничем они не отличаются" вы эту фразу заметили, и... и всё. Дальше, похоже, вы тот комментарий не видели. А он есть.
Нe ладно, ещё раз:
Не Стратегия, а if'ы, не Наблюдатель, а pub/sub или EventEmitter, не Функция высшего порядка, а функция обертка, и т.д. и т.п.
Это не так?
Вот полностью начало моего комментария (намного) выше:
Ничем. Вернее, сам вопрос поставлен примерно так же, как, например, "чем лисы отличаются от млекопитающих"
И там ещё много буков.
Но вы там в ответ написали кратенько, вот так вот:
Ничем
Ну вот, значит я правильно думаю. Спасибо за подтверждение.
_________________
Сейчас, кстати, перечитав тот мой комментарий ("Ничем. Вернее, сам вопрос поставлен примерно так же..."), я вижу, что мне тут к нему добавить наглухо нечего. Если хотите каких-то моих ответов, пожалуйста, перечитайте его.
А если хотите продолжить дальше, скажите, сначала, сколько будет в сумме один гусь плюс один петух. Ну и ещё какая разница между полицейским. Ведь на любой вопрос есть корректный ответ, не правда ли?
Ну в целом понятно, ожидаемо, классическое увиливание от неудобного вопроса развеивающего все ваши восхваления вокруг "думать паттернами" залог успеха, а всё же на самом деле оказывается таким простым и элементарным когда не закрыто за всевозможными словами, стратегиями, квестами, стрелялками.
В статье приведен "каноничная" реализация паттерна через интерфейс. В вашем же случае FK(...), LDAP(...) и т.д. - это те же самые стратегии, только реализованны через делегат.
В чем преимущество предложенного варианта над вашим? Зависит от контекста. Коль статья про тайпскрипт, представим, что нам так же и logout надо реализовать. В предложенном варианте - добавили с интерфейс нужный метод и дальше компилятор сам сообщит, в какой из реализаций мы забыли его реализовать. А в вашем варианте?
Коль статья про тайпскрипт, представим, что нам так же и logout надо реализовать. В предложенном варианте - добавили с интерфейс нужный метод и дальше компилятор сам сообщит, в какой из реализаций мы забыли его реализовать. А в вашем варианте?
Так это уже другая история, в таком случае мы изначально знаем, что нам надо больше чем 1 метод реализовывать в каждом случае и тогда конечно с точки зрения логики и безопасности надо использовать именно классы которые имплементят интерфейс и тут именно такой подход обретает реальный смысл!
class VK implements Auth { ... }
И когда добавим к интерфейсу Auth новый обязательный метод, например logout как вы и говорили, то да, компилятор будет ругаться до тех пор, пока мы его везде не реализуем.
Благодаря вашему примеру (когда больше 1 метода у всех нужно реализовать) вся суть этой затеи стала понятна) В противном случае, смысла не имеет)
В статье, видимо, забыли указать, что в функции login
должна быть еще какая-то общая логика, иначе всё это бессмысленно и проще просто саму функцию вызывать)
Т.е., почему бы тогда вместо login('twitter', '123');
сразу не написать loginWithTwitter('123');
? Количество символов то же, лишних абстракций меньше.
Если там есть общий код, то тогда есть смысл использовать "стратегию". Они нужны как раз для того, чтобы разбить код на общий и конкретные драйверы, чтобы переиспользовать общий и легко дописывать драйверы без необходимости копаться и что-то добавлять в старый код. Открытость-закрытость и прочие заморочки в действии)
ООП тут, конечно, не нужно, в статье оно просто для понтов, "стратегию" можно реализовать и простым колбэком:
import { login } from './auth';
import { loginWithTwitter, loginWithLocal } from './auth/drivers';
login(loginWithTwitter, '123');
login(loginWithLocal, "bytefer", "666");
А что если в один прекрасный момент понадобится, к примеру, добавить доп. параметры или вызовы сторонних функций? Получается, у нас login «потолстеет», и чтобы вернуть его в прежнюю форму придется приложить некоторые усилия...
function login(mode, param1, param2) {
if (mode === "account") {
// здесь предаем param1
loginWithPassword(param1);
} else if (mode === "email") {
// а здесь param2
loginWithEmail(param2);
} else if (mode === "mobile") {
// а здесь еще сделаем сайд-эффект
makeSideEffect();
loginWithMobile();
}
// А потом добавим еще 1001-проверку, которые также возможно потребуют
// доп. параметры или предварительные обработки.
// ...
}
А что если в один прекрасный момент понадобится
А что если в один прекрасный момент на голову упадет кирпич? Будем в каске ходить 24/7?)
А что если в один прекрасный момент асфальт под ногам провалится? Будем передвигаться строго по воде?)
А что если в один прекрасный момент ещё 2 миллиона параметров и условий в систему добавится?
А что если в один прекрасный момент ... можно продолжать до бесконечности.
Я понимаю стремление предусмотреть вообще все возможные варианты развития событий, но ради этого превращать код в какашку, нет спасибо) YAGNI и KISS в помощь в этом вопросе)
YAGNI и KISS это чисто рекомендации, и слепо следовать этим правилам не есть хорошо. Так же как и пихать паттерны куда не попадя. Важен все-таки баланс.
Например, весь код можно и в одном файле написать. А что, портянка кода как на ладони и лазить никуда не надо, все "чертовски просто", KISS "работает".
Вот только со временем всю эту "простоту" будет все сложнее и сложнее поддерживать. Поэтому код и раскладывают по папочкам и файлам с красивыми именами.
То же самое и с функцией login. Писать в функции множество if/else условий для вызова разных функций ради "простоты" не является примером следования YAGNI и KISS, так как это будет сложнее поддерживать в дальнейшем. Поэтому тут и применяют паттерн стратегия.
Наличие any
в каждом из примеров огорчает. Не так уж сложно нормально типизировать всё это.
Важным функционалом почти любого веб-приложения является регистрация пользователя (аутентификация) и выполнение пользователем входа в систему (авторизация)
аутентификация это проверка подлинности, а авторизация предоставление доступа.
В ООП новичек, смотрю реализацию Handler, можете объяснить для чего в class Route в super.get передается callback? он же ни где по цепочке use не будет вызван, или я ошибаюсь? А если все же и будет вызван, то в дальнейшем в этом методе он будет вызван повторно и мы получим два результата на route.get?
TypeScript: паттерны проектирования. Часть 1