Недавно на подкасте Spring АйО мы обсуждали новые свитчи в Джаве — с паттерн-матчингом и деструктуризацией. Я тогда ещё выразил мнение, что всё это неправославно, по-зумерски и отход от принципов ООП.
Не от инкапсуляции, полиморфизма и наследования, а вообще от подхода. Новые свитчи будут провоцировать разработчиков писать код по-новому, а не так, как завещали нам наши далёкие предки. С нарушением традиций, норм и устоев. Как учит Кейси Муратори, если вы понимаете о ком я.
Но какие они вообще были эти устои? Каким было ООП, когда всё только началось и чем это отличается от свитчей, до которых мы в конце концов докатились?
Источник ООП
В Джаву ООП пришло из C++. В С++ ООП попало от Бярны (наверное, это наиболее правильное произношение) Страуструпа, по совместительству автора языка.
А сам Страуструп откуда почерпнул идеи ООП? По его собственному признанию, он взял их из языка программирования Simula, предназначенного для разработки симуляции сложных систем.
Этот язык разработали в норвежской лаборатории Кристен Найгард и Оле-Йохан Даль. В 1967 году между прочим. Наверное, 1967 год это достаточно давно, и можно смело считать, что ООП впервые появилось в Simula?
А вот и нет. При разработке Simula норвежцы использовали идеи Энтони Хоара, также известного, как автора алгоритма быстрой сортировки.
Структуры с дискриминатором
Хоар хотел сделать что-то вроде discriminated unions. То есть структуры, в которых могут быть разные наборы полей, в зависимости от типа. А чтобы разработчик не допустил ошибку и не попробовал получить из структуры поле, которого там нет, в структуре всегда было поле, где был указан её тип. То есть был дискриминатор.
Предполагалось, что разработчик будет писать код как-то вот так. В переменной е тут находится какое-то алгебраическое выражение, которое может быть константой, переменной или чем-то ещё.
consider e when constant then ... when variable then ... when pair then ...
Ничего не напоминает? Это же практически один в один switch c паттерн матчингом из новой Джавы!
switch (e) { case Constant c: System.out.println(c.value()); break; case Pair p: System.out.println(p.left() + ", " + p.right()); break; case Variable v: System.out.println(v.value()); break; }
Для наглядности я добавлю под спойлер пример на джаве, который можно запустить. Только не ищите там большого смысла, я только хотел показать, что по форме это то же самое. Смыслосодержащий код в самом начале, дальше всякие объявления интерфейсов.
Скрытый текст
public class Main { static void print(Expression e) { switch (e) { case Constant c: System.out.println(c.value()); break; case Pair p: System.out.println(p.left() + ", " + p.right()); break; case Variable v: System.out.println(v.value()); break; } } public static void main(String[] args) { print(new ConstantImpl(123)); } } sealed interface Expression permits Constant, Variable, Pair { } sealed interface Constant extends Expression permits ConstantImpl { int value(); } sealed interface Variable extends Expression permits VariableImpl { int value(); void set(int newValue); } sealed interface Pair extends Expression permits PairImpl { int left(); int right(); } record ConstantImpl(int value) implements Constant { } final class VariableImpl implements Variable { private int value; @Override public int value() { return value; } @Override public void set(int newValue) { value = newValue; } } record PairImpl(int left, int right) implements Pair { }
То есть ещё в 1966 году, в языке, от которого потом отпочковалось всё известное нам ООП, уже был типобезопасный способ доступа к полям произвольного класса.
И в Simula эта фича тоже была, только за неё отвечало ключевое слово inspect.
А вот в C++ ничего такого уже нет, потому что Бьярна счёл эту возможность вредной и не стал переносить в свой язык. По его мнению она делала код менее модульным, и задачи, которые решались с её помощью, лучше было решать с помощью полиморфизма.
Вот так вот. Энтони Хоар дал, Бьярна Страуструп взял.
switch с паттерн-матчингом – это и есть ортодоксальное ООП!
Я это всё к чему. Как выясняется, идея свитчей по типам структур с последующим доступом к их полям была в ООП с самого начала! Просто она была утеряна при переходе от Simula к C++.
И то, что сейчас делает Джава, это, получается, не отход от изначального ООП, а наоборот, возврат к истокам! Да, Страуструп смог остановить прогресс на 40 лет. Однако жернова истории, хотя и крутятся медленно, в конце концов перемалывают всё.
Посмотрите выступление Кейси Муратори!
Возможно, вам интересно, откуда я знаю такие интересные и захватывающие факты из истории языков программирования. Тут могу вас обрадовать. Всё это и намного больше можно узнать из недавно опубликованного на Ютубе доклада Кейси Муратори. Того самого Кейси Муратори, который давно уже ведёт борьбу против ООП, Solid, а также всего что с ними связано. И, кажется, ведёт по очкам ))) . Держите линк!
P. S.
Идея свитчей по типу, похоже, принадлежит именно Хоару, но вот сама идея типизированных структур из N полей заимствована им у Дагласа Росса в Mit Servomechanisms laboratory, предположительно, в середине пятидесятых годов. Росс даже не называл эти структуры структурами, у него для них было специальное слово — плекс. В этих самых плексах уже были поля, и аналоги виртуальных функций. Только наследования тогда ещё, кажется, не было.
В середине пятидесятых! 70 лет назад!

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм — Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано
ссылка на оригинал статьи https://habr.com/ru/articles/934514/
Добавить комментарий