Регулярно советую учиться понимать код крупных проектов, разбираясь прежде всего в используемых структурах данных, и сам этим регулярно занимаюсь. И хотя это хорошо работает в одних случаях, но чаще всего я в итоге обнаруживал, что полностью заблудился.
И тут я понял: несмотря на то, что я внимательно просмотрел все определения структур данных в некотором крупном проекте, я не понял, что они означают в контексте системы в целом. Я могу например разобраться (или даже в редких случаях увидеть в комментах), что "связь между кластерами определяется временем создания, буферами отправки и приёма и собственно коннектом", довольно хорошо понимая, что такое эта связь между кластерами и что с ней можно делать, однако в этом проекте куда чаще активно используются такие термины, как "лист" (и не в смысле дерева), а также множество неопределённых терминов; например, не то что никакой информации мне не дало, а скорее даже больше запутало изучение структуры "SharedItem", которая, как оказалось, имеет Id, содержимое и представление. Ну и?
В хорошей документации имеется несколько частей, которые я рекомендую изучать новичкам в первую очередь. Прежде всего это руководство по ключевым файлам (синтаксическим единицам) и структурам данных (семантическим единицам). Однако больше всего хотелось бы увидеть некоторую карту/раскладку имён -- объяснения смысла и цели часто используемых идентификаторов в коде проекта.
И тут я понял: несмотря на то, что я внимательно просмотрел все определения структур данных в некотором крупном проекте, я не понял, что они означают в контексте системы в целом. Я могу например разобраться (или даже в редких случаях увидеть в комментах), что "связь между кластерами определяется временем создания, буферами отправки и приёма и собственно коннектом", довольно хорошо понимая, что такое эта связь между кластерами и что с ней можно делать, однако в этом проекте куда чаще активно используются такие термины, как "лист" (и не в смысле дерева), а также множество неопределённых терминов; например, не то что никакой информации мне не дало, а скорее даже больше запутало изучение структуры "SharedItem", которая, как оказалось, имеет Id, содержимое и представление. Ну и?
В хорошей документации имеется несколько частей, которые я рекомендую изучать новичкам в первую очередь. Прежде всего это руководство по ключевым файлам (синтаксическим единицам) и структурам данных (семантическим единицам). Однако больше всего хотелось бы увидеть некоторую карту/раскладку имён -- объяснения смысла и цели часто используемых идентификаторов в коде проекта.
🔥12👍4✍3
Многие современные API существуют десятилетиями (например, Windows API наглядный пример). Чем шире используется система, и чем больше требуется совместимости между версиями, тем ситуация печальнее. Например, есть такая глобальная система бронирования авиабилетов SABRE, API которой существует уже 60 лет ))) и если у вас когда-либо был неудачный опыт работы с авиакомпанией, есть шанс, что частично это было связано с её API.
Когда на ваше API завязано множество сторонних ИТ-систем, вы, возможно, уже никогда не сможете изменить поведение вашего API.
Недавно консультировал небольшую команду по теме дизайна API (в области AI, ага :), и в процессе придумал один очень простой, очень поучительный и очень наглядный use case, который считаю особенно умным ))) Скоро расскажу курсантам в СильныхИдеях. Посмотрев на 5 строчек кода (определение типа), вы сразу поймёте важный принцип проектирования долгосрочно развивающихся API.
Когда на ваше API завязано множество сторонних ИТ-систем, вы, возможно, уже никогда не сможете изменить поведение вашего API.
Недавно консультировал небольшую команду по теме дизайна API (в области AI, ага :), и в процессе придумал один очень простой, очень поучительный и очень наглядный use case, который считаю особенно умным ))) Скоро расскажу курсантам в СильныхИдеях. Посмотрев на 5 строчек кода (определение типа), вы сразу поймёте важный принцип проектирования долгосрочно развивающихся API.
🔥11🫡3✍1
Заметка на хабре про SOLID -- классический пример
отсутствия университетского образования незнания фундаментальных основ, когда изучаешь темки поверхностно as is, без понимания принципов, заложенных в их основу (SOLID например уже как следствие разбираем на моём треке по ООАП).
А кто просто почитал по SOLID статейки уровня википедии и пытается их бездумно применять, так и будет всю жизнь жутко косячить, думая что SRP - это вот такое =>
"Рассмотрим персонажа ролевой игры (RPG). Он может обладать такими возможностями, как перемещение, атака, взаимодействие с окружающей средой и отображение анимации. Придерживаясь SRP, можно было бы разделить эти функциональные возможности на отдельные классы, такие как CharacterMovement, CharacterCombat, CharacterInteraction и CharacterAnimation."
)))
А кто просто почитал по SOLID статейки уровня википедии и пытается их бездумно применять, так и будет всю жизнь жутко косячить, думая что SRP - это вот такое =>
"Рассмотрим персонажа ролевой игры (RPG). Он может обладать такими возможностями, как перемещение, атака, взаимодействие с окружающей средой и отображение анимации. Придерживаясь SRP, можно было бы разделить эти функциональные возможности на отдельные классы, такие как CharacterMovement, CharacterCombat, CharacterInteraction и CharacterAnimation."
)))
🔥6✍5🏆2❤1
О языках с выразительными системами типов обычно говорят: "Если оно проверяет типы, то, вероятно, всё работает". Это происходит, в частности, с чистыми функциями с полиморфными типами -- тут в итоге получается столь мало вещей, которые можно сделать с каждым входом, что иногда единственная разумно выглядящая функция, которую удаётся написать, и становится единственно верной. То есть, в некоторых случаях можно просто сгенерировать функцию из сигнатуры типа.
Например, есть такая штука, как джанглоид -- кусочек кода, который синтезируется автоматически и выполняет некоторый условно клиентский запрос к API на основании заданных типов входных и выходных значений. Так вот, формальная теория джанглоидов была разработана в начале 2000-х, задолго до явления хипстерских AI-ассистантов. Джанглоиды отлично комбинируются, и на их основе для Eclipse (основной Java IDE того времени) был разработан плагин, который выдавал адекватные подсказки и варианты кода, и, в частности, нашёл решение 18 из 20 задач.
"Jungloid mining: helping to navigate the API jungle"
Это я к тому, что если чётко описать типы входных и выходных данных функции, то её логика будет столь прозрачна, что её можно формировать достаточно простыми приёмами, "не думая". Причём специально под это есть хорошие практики, в СильныхИдеях разбирал одну такую в материале "Как проектировать ко-рекурсивные программы" (структура программы следует за используемой ей структурой данных.).
Но есть важный и контринтуитивный нюанс в понятии "чётко описывать типы". Этот момент тоже разбираем в СИ, потому что чем конкретнее тип, тем, парадоксальнее, большее количество реализаций он допускает. И наоборот, чем больше тип -- "дженерик", чем более он абстрактный, тем меньшее количество реализаций возможно.
=
Духовным наследником джанглоидов стал красивый проект SyPet
"SyPet will automatically find a sequence of API calls from these Java libraries that will pass all test cases provided by the programmer. "
но к сожалению тоже заброшен 5 лет назад.
Затем эти алгоритмы были расширены на полиморфные типы: проект Hoogle+, автоматическая генерация программы на Haskell на основе их сигнатур.
hoogleplus.goto.ucsd.edu
hoogle_plus
Например, есть такая штука, как джанглоид -- кусочек кода, который синтезируется автоматически и выполняет некоторый условно клиентский запрос к API на основании заданных типов входных и выходных значений. Так вот, формальная теория джанглоидов была разработана в начале 2000-х, задолго до явления хипстерских AI-ассистантов. Джанглоиды отлично комбинируются, и на их основе для Eclipse (основной Java IDE того времени) был разработан плагин, который выдавал адекватные подсказки и варианты кода, и, в частности, нашёл решение 18 из 20 задач.
"Jungloid mining: helping to navigate the API jungle"
Это я к тому, что если чётко описать типы входных и выходных данных функции, то её логика будет столь прозрачна, что её можно формировать достаточно простыми приёмами, "не думая". Причём специально под это есть хорошие практики, в СильныхИдеях разбирал одну такую в материале "Как проектировать ко-рекурсивные программы" (структура программы следует за используемой ей структурой данных.).
Но есть важный и контринтуитивный нюанс в понятии "чётко описывать типы". Этот момент тоже разбираем в СИ, потому что чем конкретнее тип, тем, парадоксальнее, большее количество реализаций он допускает. И наоборот, чем больше тип -- "дженерик", чем более он абстрактный, тем меньшее количество реализаций возможно.
=
Духовным наследником джанглоидов стал красивый проект SyPet
"SyPet will automatically find a sequence of API calls from these Java libraries that will pass all test cases provided by the programmer. "
но к сожалению тоже заброшен 5 лет назад.
Затем эти алгоритмы были расширены на полиморфные типы: проект Hoogle+, автоматическая генерация программы на Haskell на основе их сигнатур.
hoogleplus.goto.ucsd.edu
hoogle_plus
🔥2❤1👍1
В России вчера был официально запущен Mos.Hub -- типа, импортозамещённый аналог гитхаба.
Внимание, вопрос:
- он тоже работает под Microsoft Windows?
-- используют ли Mos.Hub разработчики Mos.Hub для создания Mos.Hub?
-- и, в частности, может ли Mos.Hub откатить Mos.Hub чтобы пофиксить Mos.Hub, когда Mos.Hub сбойнул?
Внимание, вопрос:
-- и, в частности, может ли Mos.Hub откатить Mos.Hub чтобы пофиксить Mos.Hub, когда Mos.Hub сбойнул?
🤔17👏2🫡2🔥1😇1
Наследование -- это создание новой реализации на основе старой. Аналогично, вы расширяете интерфейс, просто добавляя ещё пару методов. Никакого наследования.
Если вы планируете просто добавить новые функции в класс, то вы можете использовать композицию или наследование -- код получится почти одинаковым, тривиально преобразуемым в оба варианта, без разницы.
Этот подход фактически поддерживается и во многих функциональных языках в виде тайп-классов.
Дело в том, что вы не можете использовать "родительский класс" (пусть и абстрактный) как "интерфейс" хотя бы потому, что не будет нормально работать тайп-чекинг. Классы это реализации интерфейсов, их некорректно смешивать, согласно теории типов.
Вообще, наследование это труднейшая часть теории объектов. Обвинять кого-то, что он "не понимает наследование" всё равно, что обвинять его, что он "не понимает алгебру/пространства Chu применительно к квантовой физике".
Если вы планируете просто добавить новые функции в класс, то вы можете использовать композицию или наследование -- код получится почти одинаковым, тривиально преобразуемым в оба варианта, без разницы.
Этот подход фактически поддерживается и во многих функциональных языках в виде тайп-классов.
Дело в том, что вы не можете использовать "родительский класс" (пусть и абстрактный) как "интерфейс" хотя бы потому, что не будет нормально работать тайп-чекинг. Классы это реализации интерфейсов, их некорректно смешивать, согласно теории типов.
Вообще, наследование это труднейшая часть теории объектов. Обвинять кого-то, что он "не понимает наследование" всё равно, что обвинять его, что он "не понимает алгебру/пространства Chu применительно к квантовой физике".
🫡11👍4
Вообще, есть единственный стратегический вопрос, которого следует придерживаться в любом проекте, и ответу на который я стараюсь учить: Как мы можем сделать это правильно?
Если вы осознанно не атакуете сложность, она обязательно будет атаковать вас.
Если вы осознанно не атакуете сложность, она обязательно будет атаковать вас.
👍10🔥5
Вы знаете, что такое индустрия стоимостью в миллиард долларов? Например, это производство маленьких кусочков пластика на концах твоих шнурков для кроссовок.
Оборот индустрии картонных коробок в США -- 41 миллиард долларов. Для сравнения, НФЛ зарабатывает в год 13 миллиардов долларов, МЛБ -- 9 миллиардов, НБА -- 5 миллиардов и НХЛ -- 4 миллиарда долларов.
Но что, по-вашему, более достижимо -- попасть в НХЛ, как наш вратарь Сергей Бобровский, или начать бизнес по производству картонных коробок? Или, может быть, создать ИТ-стартап в сфере AI, которая уже в этом десятилетии перерастёт триллион долларов?
Правда в том, дорогие, что ваши самые глупые и простые идеи часто срабатывают лучше всего. Ориентируйтесь на как можно более массовое и простое применение сервиса.
Джеймс Альтушер, автор десятков книг включая классную "Учитесь говорить "Нет", участвовавший в создании множества стартапов, управляющий крупными хедж-фондами, рекомендует простой приём: завести привычку каждое утро записывать 10 идей по актуальной для вас теме.
"А если просто не получается придумать 10 идей? Есть один фокус: если не можете придумать 10 идей, придумайте 20. ...Вы слишком сильно на себя давите. Перфекционизм – ВРАГ идейной мышцы. Мозг пытается защитить вас от вреда, мешает придумать глупую идею, которая вас опозорит или принесет боль. Этот механизм можно отключить, заставив мозг придумывать плохие идеи...
Делаете два столбца, в левом – список идей, в правом – список ПЕРВЫХ ШАГОВ для их реализации. Запомните: для каждой идеи надо записать только один первый шаг."
Ричарду Брэнсону (миллиардер, слетавший в космос в 70 лет, основатель консорциума Virgib Group с сотнями компаний -- так назвал, потому что был "девственником" в бизнесе), когда он ещё был рядовым издателем журнала, однажды не понравилось обслуживание авиакомпании, которой он летал. Поэтому у него возникла идея: "Я создам новую авиакомпанию". Как это можно создать авиакомпанию с нуля и без денег? Его первый шаг: он позвонил в Boeing и узнал, можно ли взять у них в аренду самолет. Ну и закрутилось.
...А сегодня в одной только теме ИТ-стартапов AI куча вполне продаваемых идей просто на поверхности лежит, пишу и тут в частности регулярно.
Оборот индустрии картонных коробок в США -- 41 миллиард долларов. Для сравнения, НФЛ зарабатывает в год 13 миллиардов долларов, МЛБ -- 9 миллиардов, НБА -- 5 миллиардов и НХЛ -- 4 миллиарда долларов.
Но что, по-вашему, более достижимо -- попасть в НХЛ, как наш вратарь Сергей Бобровский, или начать бизнес по производству картонных коробок? Или, может быть, создать ИТ-стартап в сфере AI, которая уже в этом десятилетии перерастёт триллион долларов?
Правда в том, дорогие, что ваши самые глупые и простые идеи часто срабатывают лучше всего. Ориентируйтесь на как можно более массовое и простое применение сервиса.
Джеймс Альтушер, автор десятков книг включая классную "Учитесь говорить "Нет", участвовавший в создании множества стартапов, управляющий крупными хедж-фондами, рекомендует простой приём: завести привычку каждое утро записывать 10 идей по актуальной для вас теме.
"А если просто не получается придумать 10 идей? Есть один фокус: если не можете придумать 10 идей, придумайте 20. ...Вы слишком сильно на себя давите. Перфекционизм – ВРАГ идейной мышцы. Мозг пытается защитить вас от вреда, мешает придумать глупую идею, которая вас опозорит или принесет боль. Этот механизм можно отключить, заставив мозг придумывать плохие идеи...
Делаете два столбца, в левом – список идей, в правом – список ПЕРВЫХ ШАГОВ для их реализации. Запомните: для каждой идеи надо записать только один первый шаг."
Ричарду Брэнсону (миллиардер, слетавший в космос в 70 лет, основатель консорциума Virgib Group с сотнями компаний -- так назвал, потому что был "девственником" в бизнесе), когда он ещё был рядовым издателем журнала, однажды не понравилось обслуживание авиакомпании, которой он летал. Поэтому у него возникла идея: "Я создам новую авиакомпанию". Как это можно создать авиакомпанию с нуля и без денег? Его первый шаг: он позвонил в Boeing и узнал, можно ли взять у них в аренду самолет. Ну и закрутилось.
...А сегодня в одной только теме ИТ-стартапов AI куча вполне продаваемых идей просто на поверхности лежит, пишу и тут в частности регулярно.
🔥9🫡4✍2👍1
Jim Fan -- AI-исследователь в NVIDIA и PhD Стэнфорда, рассказал, как в Stanford Vision and Learning Lab создаётся ObjectFolder -- "a very unique dataset for multisensory object-centric learning, geared towards object recognition, reconstruction, and manipulation with sight, sound, and touch. Features 100 real-world household objects and 1,000 neural objects. Each is defined by an "ObjectFile"..."
То есть Стэнфорд создаёт объектно-ориентированный AI )))
Кстати, на днях в Scientific American вышла статья, где предполагается, что посещающие возможно Землю инопланетяне НЛОрептилоиды -- это не органические существа, а активно развивающийся где-то в других мирах AI, добравшийся и до нас. А кожаные-белковые, которые его создали, уже давно всё :)
Поэтому давайте срочно оседлаем волну экспоненциального прогресса!
До тех пор, пока мы ещё можем идти в ногу со временем...
Сэм Альтман: Я за регулирование AI-отрасли!
Также Сэм Альтман: Кроме моих работ. Мне можно доверять!
То есть Стэнфорд создаёт объектно-ориентированный AI )))
Кстати, на днях в Scientific American вышла статья, где предполагается, что посещающие возможно Землю инопланетяне НЛО
Поэтому давайте срочно оседлаем волну экспоненциального прогресса!
До тех пор, пока мы ещё можем идти в ногу со временем...
Сэм Альтман: Я за регулирование AI-отрасли!
Также Сэм Альтман: Кроме моих работ. Мне можно доверять!
🫡7👍5🤔3😇1
Как вы думаете, каково (согласно теории типов) отношение между интерфейсом и реализацией условного модуля?
Anonymous Quiz
21%
один-к-одному
50%
один-ко-многим
30%
многие-ко-многим
🤔3🤯3
Отношения между интерфейсами и реализациями (между типами модулей и самими модулями) -- это отношения "многие ко многим". Одно из направлений этого отношения общеизвестно: интерфейс может иметь несколько реализаций. Но другое направление не менее важно, но гораздо менее оценено: реализации удовлетворяют нескольким интерфейсам.
Если бы отношение между интерфейсом модуля и реализацией было один-ко-многим, то, внимательно посмотрев на несколько реализаций, мы могли бы восстановить их единственный предполагаемый интерфейс, но это невозможно, потому что существует множество таких возможных интерфейсов.
Когда я узнал, что Роберт Харпер (один из святых computer science, написавший кучу курсов для CMU) выгнал Java из учебных планов, настояв на преподавании OCaml и SML (семантику которых он описал формально), то сперва подумал, что он просто выдумывает причины, чтобы навязать свой любимый язык всем остальным. Теперь же я уверен, что он абсолютно прав, и поэтому в частности прикладной курс по ФП сделал на F#.
Java просто откровенно плоха в предоставлении нескольких интерфейсов для одной и той же реализации. Харпер пытался научить этому модульному принципу в Java в течение многих лет и потерпел неудачу. Сейчас я и сам иногда с этим сталкиваюсь, когда прошу курсантов привести примеры одной реализации с несколькими интерфейсами, и в 80% случаев получаю пример одного интерфейса с несколькими реализациями.
=
По мере роста системы становятся всё сложнее и сложнее, когнитивно сильно перегружая ум. И все же у нас есть хитрость, развивающаяся ещё с середины прошлого века и позволяющая создавать объекты гораздо большей мощности, чем может понять один человек. Этот трюк -- модульность: способность создавать что-то из частей, которые существуют независимо друг от друга и которые проще создавать по отдельности, но которые объединяются в нечто целое и гораздо большее.
Забавная вещь происходит, когда система декомпозируется на модули, а затем позволяет их комбинировать (исчисление модулей в OCaml). Если это делать правильно, то в проекте появляется новая сущность, отдельная от системы и более долговечная, чем сама система: интерфейс.
Суть модульности -- это простая теория, формализм которой укладывается всего в две строки по Харперу. В СильныхИдеях скоро будет мощный материал об этом, дам простую думательную машинку, чтобы любой программист мог сразу начать это правильно применять.
Если бы отношение между интерфейсом модуля и реализацией было один-ко-многим, то, внимательно посмотрев на несколько реализаций, мы могли бы восстановить их единственный предполагаемый интерфейс, но это невозможно, потому что существует множество таких возможных интерфейсов.
Когда я узнал, что Роберт Харпер (один из святых computer science, написавший кучу курсов для CMU) выгнал Java из учебных планов, настояв на преподавании OCaml и SML (семантику которых он описал формально), то сперва подумал, что он просто выдумывает причины, чтобы навязать свой любимый язык всем остальным. Теперь же я уверен, что он абсолютно прав, и поэтому в частности прикладной курс по ФП сделал на F#.
Java просто откровенно плоха в предоставлении нескольких интерфейсов для одной и той же реализации. Харпер пытался научить этому модульному принципу в Java в течение многих лет и потерпел неудачу. Сейчас я и сам иногда с этим сталкиваюсь, когда прошу курсантов привести примеры одной реализации с несколькими интерфейсами, и в 80% случаев получаю пример одного интерфейса с несколькими реализациями.
=
По мере роста системы становятся всё сложнее и сложнее, когнитивно сильно перегружая ум. И все же у нас есть хитрость, развивающаяся ещё с середины прошлого века и позволяющая создавать объекты гораздо большей мощности, чем может понять один человек. Этот трюк -- модульность: способность создавать что-то из частей, которые существуют независимо друг от друга и которые проще создавать по отдельности, но которые объединяются в нечто целое и гораздо большее.
Забавная вещь происходит, когда система декомпозируется на модули, а затем позволяет их комбинировать (исчисление модулей в OCaml). Если это делать правильно, то в проекте появляется новая сущность, отдельная от системы и более долговечная, чем сама система: интерфейс.
Суть модульности -- это простая теория, формализм которой укладывается всего в две строки по Харперу. В СильныхИдеях скоро будет мощный материал об этом, дам простую думательную машинку, чтобы любой программист мог сразу начать это правильно применять.
🔥17👏2
"Эксперты редко решают сложные задачи с помощью доведения до предела своих экспертных навыков решения соответствующего класса сложных задач. Сначала они тратят значительные усилия на разложение сложной задачи на подзадачи, которые можно решить с помощью обычных навыков."
-- Кент Бек
Причём скиллы композиции и декомпозиции, конечно, ортогональны, и изучать их надо осознанно по отдельности.
-- Кент Бек
Причём скиллы композиции и декомпозиции, конечно, ортогональны, и изучать их надо осознанно по отдельности.
🤔11🔥5✍1
В продолжение интерфейсов и реализаций. Например, программисты на OCaml могут писать модули, которые не привязаны к какой-либо конкретной реализации своих зависимостей. Общий термин для этого -- "динамическая архитектура", и большинство не функциональных языков поддерживают это весьма плохо. Как правило, они полагаются на #ifdef-ы -- или, что ещё хуже, на систему сборки.
Инъекция зависимостей -- распространённое противоядие, но это только часть решения. Вы можете параметризовать реализации интерфейса в Java, но простой способ -- неправильный, а правильный -- сложный. Потому что чтобы сделать это правильно, вы должны сначала запихнуть всё о модуле (включая определения типов) в один инжектируемый объект.
Инъекция зависимостей -- распространённое противоядие, но это только часть решения. Вы можете параметризовать реализации интерфейса в Java, но простой способ -- неправильный, а правильный -- сложный. Потому что чтобы сделать это правильно, вы должны сначала запихнуть всё о модуле (включая определения типов) в один инжектируемый объект.
🤯7🫡3🔥2
Хорошее:
The C4 model — misconceptions, misuses, and mistakes... includes notation, abstraction levels (number of & naming), abstraction vs organisation, ADRs, DDD, event modeling, microservices, message-based architectures, and more.
От автора учебника "Software Architecture for Developers"
Его же "The lost art of software design"
The C4 model — misconceptions, misuses, and mistakes... includes notation, abstraction levels (number of & naming), abstraction vs organisation, ADRs, DDD, event modeling, microservices, message-based architectures, and more.
От автора учебника "Software Architecture for Developers"
Его же "The lost art of software design"
👍2
Почему большинство программистов так не любят ни проводить code review, ни тем более подвергаться ему? Причин много, одна из важных, например, что когда код императивный или особенно ООП, он практически всегда будет как минимум неэлегантным, а чаще всего запутанным, и читать и править его довольно дискомфортно.
А вот когда вы разбираете код на функциональных языках, это получаются просто приятные паззлы :) Однако многие программисты тут начинают плакать, дескать, эти ваши какие-нибудь foldLeft-ы делают код совершенно нечитабельным.
Ну, это только потому, что вы не понимаете, как это работает :) Разберитесь, пройдите курсы по ФП (а для начала просто активно применяйте в своём коде map/reduce), и будете получать от использования функций высших порядков огромное удовольствие.
А вот когда вы разбираете код на функциональных языках, это получаются просто приятные паззлы :) Однако многие программисты тут начинают плакать, дескать, эти ваши какие-нибудь foldLeft-ы делают код совершенно нечитабельным.
Ну, это только потому, что вы не понимаете, как это работает :) Разберитесь, пройдите курсы по ФП (а для начала просто активно применяйте в своём коде map/reduce), и будете получать от использования функций высших порядков огромное удовольствие.
❤7🔥7🤔2⚡1
В продолжение про интерфейсы.
Например, мы вполне можем убрать из интерфейса стека специальные слова push и pop, и назвать эти операции просто add и remove. Потом мы можем создать интерфейс очереди, также используя операции add и remove. Когда я делал курсы по алгоритмам, сразу отметил, насколько похожи интерфейсы классов стека и очереди. Фактически, если заменить push и pop на add и remove, мы получим идентичный интерфейс! Не знаю, хорошо это или плохо, но люди, которые хотят объединить эти два интерфейса, встречаются примерно так же часто, как люди, которые требуют, чтобы их обслужили первыми, потому что они вошли в очередь последними.
Это показывает, что когда мы думаем об интерфейсах, мы думаем не только о том, содержит ли модуль функции с определёнными сигнатурами. Мы также думаем о спецификации -- о том, какого именно поведения мы ожидаем от этих функций. Возможно, рядом с функцией pop() есть комментарий, говорящий, что она обратна функции push(). Этот факт можно считать частью типа модуля в той же мере, что и сами сигнатуры функций, потому что знание этого факта необходимо для использования модуля! В идеале его надо сделать "физической" частью типа.
Существует несколько языков с достаточно мощными системами типов, чтобы выразить связь между push() и pop() -- например, Coq, Agda, Idris. Я могу показать вам, как это выглядит на любом из них, но к большому сожалению это совсем непрактично. Поэтому пока основное решение -- материалы из СильныхИдей, где я постоянно поясняю, как правильно думать на более высоком логическом уровне -- абстракциями, которые в обычном коде отсутствуют по определению.
Например, мы вполне можем убрать из интерфейса стека специальные слова push и pop, и назвать эти операции просто add и remove. Потом мы можем создать интерфейс очереди, также используя операции add и remove. Когда я делал курсы по алгоритмам, сразу отметил, насколько похожи интерфейсы классов стека и очереди. Фактически, если заменить push и pop на add и remove, мы получим идентичный интерфейс! Не знаю, хорошо это или плохо, но люди, которые хотят объединить эти два интерфейса, встречаются примерно так же часто, как люди, которые требуют, чтобы их обслужили первыми, потому что они вошли в очередь последними.
Это показывает, что когда мы думаем об интерфейсах, мы думаем не только о том, содержит ли модуль функции с определёнными сигнатурами. Мы также думаем о спецификации -- о том, какого именно поведения мы ожидаем от этих функций. Возможно, рядом с функцией pop() есть комментарий, говорящий, что она обратна функции push(). Этот факт можно считать частью типа модуля в той же мере, что и сами сигнатуры функций, потому что знание этого факта необходимо для использования модуля! В идеале его надо сделать "физической" частью типа.
Существует несколько языков с достаточно мощными системами типов, чтобы выразить связь между push() и pop() -- например, Coq, Agda, Idris. Я могу показать вам, как это выглядит на любом из них, но к большому сожалению это совсем непрактично. Поэтому пока основное решение -- материалы из СильныхИдей, где я постоянно поясняю, как правильно думать на более высоком логическом уровне -- абстракциями, которые в обычном коде отсутствуют по определению.
🔥6❤2👍2
Несколько потоков? Давайте запустим их в голове последовательно.
Иммутабельное состояние? В наших головах оно постоянно изменяется и читается атомарно.
Наша склонность к упрощению -- наш злейший враг. Чтобы бороться с ней, нам нужно выбирать методы и инструменты, которые не склонны к неправильному толкованию.
Иммутабельное состояние? В наших головах оно постоянно изменяется и читается атомарно.
Наша склонность к упрощению -- наш злейший враг. Чтобы бороться с ней, нам нужно выбирать методы и инструменты, которые не склонны к неправильному толкованию.
👍8🤔2