Егор Бугаенко - Объектно-ориентированное вранье
2016 ж. 8 Қар.
134 626 Рет қаралды
Ближайшая конференция - Joker 2024, 9 октября (Online), 15-16 октября, Санкт-Петербург
- -
. . . . Егор Бугаенко, Teamed.io - Объектно-ориентированное вранье
Java-конференция для студентов JPoint 2016 Student Day
Москва, 24.04.2016
То, что cейчас в Java называется ООП, почти ничего общего не имеет с тем, что должно так называться. Не дайте себя обмануть на самом старте, будьте осторожны.
Ушел переписывать сортировку пузырьком на ООП. Выделил объект пузырек. обернул в объект сортировка. Дальше запутался, помогите!
Ну изи же - пузырек нужно было обернуть в декоратор "ComparableПузырь" потом накидать эти пузырьки в список, а для списка сделать декоратор "SortedList"
Но сортировка же не объект, а функция
Создаешь класс Value, в нем 2 метода equal и greater, которые принимают на вход другой объект класса Value. Создаешь класс Sorter с методом sort, который проходит по обектам и сранивает их и возвращает отсортированный список. На самом деле слова докладчика верны и на таком принципе работает react js, но он заехал не на ту конференцию и выбрал не тот язык, в котором его концепция реализована. Ему прямая дорого в ФП, а именно в хаскель или immutable.js
@@DanilaAvdoshin вот про это и говорят в видосе. Думаете не объектами, поэтому и не сходится. Про функторы ака функциональные объекты не слышали?
Я понимаю что это ирония, но для тех кто не вьехал: Что за объект "сортировка"? Объекты называются не по принципу "что он делает", а "чем он является". Объект не может являться "сортировкой". "Пузырьком" тоже. У вас есть объект "какие-то данные", делается декоратор "отсортированные какие-то данные", у которого сортировка происходит в конструкторе (насчёт этого не совсем уверен, кажется это не совсем соответствует идеологии Егора, но хрен с ним, суть не в этом). Вы инстанцируете "отсортированное", скармливая его конструктору уже существующее "неотсортированное", у вас получается объект, содержащий отсортированное. Только не надо просить от меня объяснить почему якобы я считаю что всё это правильно, я ничего не считаю, а просто передаю вам мысль оратора как её понял я.
Егор здесь сам на себя не похож. Когда он спокоен, то рассказывает невероятно круто!
Борьба за права объектов.
А классов?
Из лекции взбодрило "моя книга стоит 41$"
Интересно, как быть с extension-методами..
Класс 2dvector, его используют другие объекты, некоторые используют его координаты раздельно для проверки каких-либо условий. Получается для каждого использования я должен генерить новый класс потомок, инкапсулирующий работу с этими координатами. В пределе по доп.классу для каждого использующего класса. Это уйма лишней работы, а обозримость и анализируемом то кода падает до нуля - я должен елозить по огромному дереву на каждый чих, чтобы понять, что происходит. Безумно.
Ваще красавчик
Доклад очень интересный, но несколько раз был задан хороший вопрос , а как эта концепция сказывается на производительности. Не на пустом же месте появились move семантика и cow. Помню в одном из проектов после профилирования, обработка строк занимала 80% машинного времени.
Интересно взглянуть на код докладчика
Причем смотреть доклад нужно ПОСЛЕ просчтения Effective Java. Правда прибегут потом фанатики и свидетели быстрого С++ и расскажут как плохо пересоздавать объекты
Доклад интересный, но действительно любопытно было бы увидеть код какого-нибудь web-приложения с таким подходом. Индустриальный стандарт все-таки Spring, Hibernate. Никуда от этого не деться. А в них такой подход, видимо, не уложится..
спасибо огромное за комменты - помогли сэкономить время, не смотреть
а поле путь файла он заполняет через конструктор, я так понял?
Thanks
37:12 - аналогия класса String, любое присвоение переменной нового значения пересоздает объект. в принципе логично. ведь файл новый. значит и объект новый.
посмотреть бы на код калькулятора в стиле ООП с такими вводными
Да, это жёстко
var sum = new SumOperator(value1, value2); sum.GetResult();
А где-нибудь есть объяснение ООП через "генетические алгоритмы" ?
А заxем они тебе, несчастный ?
А в c# такая же ситуация как с java в плане ООП? Spring, hibernate.
Не слушайте инфоциган и модников. Майтесь шарпом если маетесь.
И в шарпе вагон объектов-значений:struct,record class,record struct. Record class каешн ссылочный тип,но суть вродь та ж. Вместо изменения состояния и велосипедирования кода для порождения из текущего объекта нового с измененными значениями юзается один и тот же вшитый метод.
Так классы нужны для того, чтобы объединять объекты, которые будут иметь схожие характеристики и схожее поведение. Если объекты будут без привязки к классам, тогда будет много дублирующегося кода. Разве не так?
это как в жаве можно объект создавать, не указываю его тип)
Нет, классы для этого совершенно не обязательны. Иначе процедурное или функциональное программирование не могли бы существовать в принципе. Помимо наследования через классы существует прототипное наследование в js, а самое главное, существует такое явление как "композиция".
По моему опыту: схожие объекты объединяются классом без логики и всеми публичными полями, либо стуктурой. После этого создаются классы-конвеер которые эти объекты обрабатывают. Но это не ООП. Происходит сепарация данных и логики, как это делается в функциональном программировании. Объектное же подразумевает инкапсуляцию логики и данных внутри одного класса.
в целом интересно, но не очень понятно как это применить в суровой реальности enterprise. мне пока сложно представить, как можно этой концепции строго придерживаться на практике. нам с фронта может прилететь большая котлета с частично заполненными полями, которых в принципе много. это все ифами и декораторами разруливать чтобы распихать по маленьким классам? я думаю спринг, хибер и иже с ними были созданы не от того что их создатели процедурно мыслят, а как необходимое зло.
Если фронт способен пуляться такими котлетами, значит с самим фронтом что-то не так. Но в антрепризе да, куча легаси и совершенное отсутствие времени, средств и желания что-то переделывать. Кобол вам в руки, и будет полное антреприз-счастье, да.
то о чем он говорит для этого есть целая аббревиатура, не помню как называется, там этих парадигм и принципов туева хуча, господин Немчинский хорошо об этом расскажет
Этот ролик нужно промаркировать "45+" )))
я так понял нужно из Явы сделать Хассель =)
Не знаю по мне слишком заморочено, есть люди которые едят только мясо, они говорят есть овощи не правильно вовсе. Есть и другие психи кто одну траву жрет и приводит 100500 пруфов что так правильно жить. Но истина посередине, плодить миллиарды микроклассов это утопия, но и создавая объекты надо думать надо ли пихать везде сеттеры, и думать о доступе, так же использовать оптимальные функции для экономии ресурсов железа, и тд, не надо кидаться в крайности, если вам дали много инструментов это не значит что есть суп надо вилкой, держа её пинцетом зажатым в левой ноздре.
я вообще не программист, а ядерный физик с образованием математика, но спрошу:) Чем микроклассы по сути отличаются от обычных процедурных функций типа того же fopen? это не отход ли от ООП? И чем декораторы с новыми методами отличаются от классов, наследующих примитивный класс File?
декоратором ты же оборачиваешь функции или методы классы и даешь им новое стандартное поведение, можешь думать о них как о pre-hooks, дюже удобная штука, про класс вообще не понял к декораторам отношения не имеет
Возникли те же вопросы...
Ничем кроме покупки книги этого товарища) Есть такая поговорка - если у человека есть лишь молоток, он везде будет видеть гвозди. "НЕ используйте хибернейт и спринг в написании программ на джава"... Мне действительно жаль себя и всех людей которые потратили время на просмотр этих фантазий на тему программирования.
Отличный доклад, объясняющий в том числе ценность SOLID-принципов.
Солид это как есть мацу с салом под одеялом пока аллах не видит. Типа ФП хуета поебота, а на деле 10001 интерфейс и классы-процедуры.
дело в том, что мыслить можно как угодно, хоть объектами. Можно придумывать и "живые сущности")). Но в итоге все сведётся к обычному процедурному коду)
процессор к сожалению не "думает" объектами )
Да, это правда, но все эти концепции способствуют разным гарантиям в работоспособности этих инструкций)
Не поняла: какое такое "всё", и почему оно сведется к обычному процедурному коду?
Инкапсуляция - обьеденение данных и операций над данными Сокрытие - препятствие доступа внешней среды (средствами языка) к данными; описанию объекта (его полей). Часто нет строго отделения инкапсуляции от сокрытия - это норма(и печально)
Бред. Объединение данных и методов - это понятие оопнутого класса, а не инкапсуляции. Сокрытие скрывает, Карл! А не ограничивает доступ. "Сокрытие", которое ничего не скрывает - сокрытием не является.
Предлагаю ввести в ООП паттерн "Гипнотизер", тогда можно будет использовать геттеры и сеттеры. xD
ору
Design patterns это плохо, это не ООП. Чтобы не было больших объектов с кучей методов мы будем оборачивать объекты... А разве обертка не паттерн?
Все яд,все лекарство(с) к-классика.
Доля истины в этой идее есть. Особенно если не фиксироваться на объекте как на программной сущности, а представлять его себе как сущность информационную, как некую "душу", которая способна менять тела в виде программных объектов при необходимости, если рассматривать объекты как фрагменты данных, а не конкретные области памяти Только вместо декораторов стоит пользоваться разумной необходимостью Вам не нужен класс, который умеет всё. И вам не нужен класс, который не умеет ничего. В каждом конкретном случае вам нужно что-то конкретное, какая-то сущность, которая обладает строго ораниченным функционалом. Это не только ограничивает область контекста, но и стабилизирует архитектуру, делает ее жесткой и устойчивой. Вот от этой идеи и стоит отталкиваться. Да в принципе она и так везде используется, если посмотреть со стороны: одни и те же по сути данные проходят через множество слоев, но в каждом слое они обернуты в разные объекты с разными характеристиками. Когда объект находится в нижних слоях, он несет в себе множество "лишних" низкоуровневых данных, когда добирается до верхних слоев, в нем остается только самый необходимый минимум данных. И на пути от железа вовне и обратно объект множество раз "перерождается" в разных формах, с разными характеристиками Только в таком виде та концепция, которую докладчик пытается выразить, обретает хоть какой-то смысл
Я сейчас ищу работу, после собеседования понял, что пишу в функциональном стиле
Процедурный программирование
31:17 это какой-то лютый пиздец, декоратор чтобы читать построчно, давно уже все придумали два разных метода, при этом делаем отдельными методами все для подготовки файла к чтению, потом тупо имплементируем прочитать все или прочитать и вернуть строку, в первом случае тупо будет определять границы файлы и возврощать строку, во втором по символ переноса строки и проверять что не выходим за границы файла на следующей итерации.
Вообще по уму для получения массива строк из массива байт нужна отдельная сучность-фильтр. Которая сможет работать не только с файлами.
Создатели java - люди не глупые.
Егор - мозг!
Null - "большая ошибка", не должно быть его в ООП см. ответ 39:38
нул режит слух..
@@zeor4044 режет слух, когда ноль называют нуль... А нул это вполне конкретное ничто в математике
Егора не смущает что такие монстры как Netflix написаны на Java? 😹
Почему getters и setters это плохо? Почему извне мы можем делать всё что угодно с этими данными? Отнюдь нет. С данными делать можно только в рамках дозволенного функцией. Например у нас есть функция set с параметром int. В неё можно поместить число в диапазоне 0..255, а мы поместили -15 или 300. Нам не нужно прописывать отдельные случаи с такими данными, функция set это уже реализовала. В SFML есть класс sf::Text, в нём есть функция setColor. Через setters тексту нельзя применять цвет? Как иначе тогда? 36:14 У нас есть 2 варианта: файл переименовывается в той же папке или по новому пути. В чём принципиальная разница между методами Rename() и setName() если тело обоих методов одинаковое, разница только в трёх буквах.
Не являюсь сторонником выступающего, но что касается сеттеров, то с некоторыми оговорками он прав: любое изменяемое состояние (класса) ведёт к проблемам, особенно в многопоточном окружении. Ибо его надо синхронизировать. А любая ошибка при реализации синхронизации приводит к трудно воспроизводимым и исправимым багам. И даже правильная реализация может приводить к частым блокировкам потоков и потере производительности. Кроме того, и вне многопоточки код с отсутствием изменяемого состояния гораздо проще читается и воспринимается. Если вы хотите изменить состояние объекта, то, как автор и сказал, просто создаёте новый на его место. В этом случае ваша функция setColor вернёт новый sf::Text - дубль старого, но с изменённым цветом. Так это работает в ФП во всяком случае.
@@zachemny По поводу setColor и sf::Text. Я увлекаюсь кибербиологией, эволюционным моделированием, там каждая секунда на счету. Если заново создавать sf:Text с его атрибутами (цвет, шрифт, размер, атрибуты стиля, толщина, цвет контура шрифта, позиция на экране и т.д.) всё это отдельные функции и при каждом создании нового текста ради цвета придётся вызвать 8 функций. Я подозреваю каждый вход в функцию, если она не inline кушает ресурс процессора. Способ который предлагаете вы, возможно более читабелен, но боюсь медленней чем тот, который использую я (ради цвета вызываю только setColor()).
@@UFO26 Ну, я не пытаюсь навязать вам данный подход. В каждом конкретном случае он может оказаться неудобен или даже неприменим. Хотя выглядит несколько странно, если у вас моделирование привязано к изменению или выводу текста, обычно эти задачи разносят, и там, где идут хардкорные вычисления, текст не генерируется. Хотя, возможно, я что-то неправильно понял. 8 функций для создания объекта вызывать по идее не нужно, вызывается клонирование предыдущего объекта с изменением его свойства. Но поскольку иммутабелен весь текст, то клонирование придётся повторить для всей предыдущей части части составного объекта (графа объектов). Вообще же иммутабельный подход к структурам данным считается более медленным, зато приводит к упрощению кода (особенно многопоточного). Ускорение тут достигается засчёт более эффективного распараллеливания. Ради каждого изменения приходится изменять почти весь граф объектов (начиная с корня до тек. узла, т.к. они все иммутабельны). Но, в то же время, это можно делать в отдельном потоке, что может в итоге оказаться даже эффективнее, чем блокировать весь граф для др. потоков на время внесения изменений. Привнесение изменяемости для классов в этом контексте считается оптимизацией и выполняется только тогда, когда все остальные средства уже исчерпаны, а скорости всё ещё не хватает.
@@zachemny спасибо за развёрнутый ответ.
@zachemny, хм, учитывая то что вы описали как фп, предметно ориентированное выходит синтезом фп и ооп.забавно. объекты-значения как раз таки immutable
Thread в помощь ... братан
Ещё из недавнего. Про жертв ООП. НИИИС пишет программу под конкретное железо для конкретного изделия. Наш выпускник МФТИ поставляет им исходный кода на С++ с классами, которые никем не наследуются, не инкапсулируются и не полиморфируются, просто потому что в ФПО для железа это не нужно, ествественно, ребята из НИИИС переписывают его на на чистейшем незамутненном С:-)
И тут все зарыдали в связи с отсутствием транспилятора C++ в чистый и незамутненный C.
Идеи понятные, интересные. Столпы ООП (типа Гради Буча) вобщем-то и учат изначально такому мышлению. Однако потом наступает реальный мир, где вместе пятидесяти классов тупо проще сделать один и допустить, что в нём часть свойств могу быть null. Тчк. И когда тебе твой бизнес-манагер стучить по голове со словами "когда будет сделано?" по 10 раз в день, ты рано или поздно будешь всё чаще и чаще выбирать менее time consuming вариант. Так работает практика. За очень редким исключением, когда какие-то решения могу быть проработаны наперёд и ясно, что они дают некую гибкость на будущее и позволят в будущем сэкономить labor cost. Однако это тоже зачастую нивелируется реальной ситуацией, где есть масса проектов, которые толи проживут ещё месяц, толи нет. И далеко не всегда в реальном мире прям нужно заморачиваться с правильностью ООП.
т.е. операция "переименовать файл" должна ну просто в обязательном порядке создавать новый объект и удалять старый объект? установка цвета для кнопки на экранной формочке обязательно должна уничтожать старую кнопку и создавать новую, с подчисткой мусора, перестройкой layout и вот этим вот всем? и как мы раньше жили, не умея программировать самым в мире правильным образом!
А какой язык максимально близок к этим идеям?
Автора замкнуло просто си++ и джаве в основном на джаве, автор старый ничего нового в жизни не хочет и поэтому не понимает, что забивать рубанком гвозди такая себе идея. Вся штука в том что современный программист для эффективной работы должен как минимум уметь в три - четыре языка, знать сильные и слабые стороны и использовать под конктретные задачи, а не так что взял джаву эту и громоздишь монолит на миллионы строк из говна и палок. Вторая проблема заказчик который редко когда знает и понимает что ему надо и получается: "потсоны тут проект фигня мне тут бамбуковый шалаш без сортира" к концу проект: "ээээ я чот в Дубае побывал нахуй мне этот шалаш давайте его в небоскреб переделаем, бабки есть я плачу"
@@denisviklov4596 можно говношлёпить "по быстрому", а можно писать грамотный красивый код. Второе конечно же гораздо сложнее, отсюда и такая реакция)
Java например. Попробуйте выкинуть те 3 пункта из вашей практики и посмотрите как вы будете писать код.
Эйфель. Самый чистый ООП.
русский
Не использую ООП вообще, никаких классов тоже не использую, а тупо функциями все всегда пишу. Интернет бизнес свой. И у меня нормально. Есть две квартиры и машина. Путешествую еще часто. Так что это все просто инструменты. Которыми можно пользоваться, а можно и не пользоваться. Не нужно думать, что знание ООП и умение мыслить как-то иначе что-то вам даст какие-то преимущества. Самое главное пишите так как думаете, как вам удобнее. А все эти тенденции и модные тренды это пусть в гугле и фейсбуке там сами на своем ООП пишут. Мне оно даром не нужно. Кода больше получается, читаемость хуже. Понять код зачастую тоже сложнее. И зачем оно нужно такое? Так же ка и стрелочные функции и всякие сокращения я тоже терпеть не могу. Код должен оставаться быть понятен вам даже если прилично поддали. Или проснулись среди ночи.
Просто разные концепции В одном случае цель это эффективный бизнес. Первичен доход, а не инструменты. От инструментов прямой выгоды нет, главное чтобы оно хоть как-то работало, денюжка капает просто за счет бизнес-процессов В другом случае цель это эффективное ремесленничество, мастерство. Первична производительность этого самого мастерства, количество заказов в единицу времени: чем больше заказов выполнишь, тем больше заработаешь, никаких альтернативных бизнес-процессов, кроме самого ремесленничества, тут нет, денюжку приносят только закрытые заказы. Тут уже вступает в игру разница в инструментах: одни инструменты позволяют достичь результата раньше и с меньшими усилиями, чем другие, но они сложнее и освоить их труднее, как например голый блокнот против навороченной IDE, или например самописный код против фреймворков и библиотек. Тут проявляется разница в подходах: в голом блокноте весь процесс производства ты выстраиваешь сам, а в IDE ты вынужден учить как с ней работать и осваивать те методики разработки, под которую эта IDE проектировалась, точно также и всю архитектуру самописного кода, все требования к нему ты тоже определяешь сам, но при использовании фреймворков и библиотек ты вынужден обучаться тому, как их использовать, вынужден использовать именно тот подход, под который они были спроектированы, а значит вынужден осваивать и использовать ООП, паттерны, заиметь понимание основных алгоритмов и структур данных, их свойств, ведь все это там внутри библиотек и фреймворков зашито, ожидается на входе, и получается на выходе, и с этим хочешь-не хочешь, но придется работать, чтобы повысить эффективность своего мастерства. Без фреймворков и библиотек писать тоже можно, но это явно займет несравнимо больше времени и затрат, чем развернуть фреймворк или подключить библиотеку и сразу получить значительную долю итогового функционала
Сам автор в начале говорит что писать код ему не комильфо
И тут мы приходим к функциональному программированию, где данные не меняются. ООП это натягивание концепций реального мира на программирование. Вот в реальном мире есть объект пациент, сегодня к него есть аппендикс, завтра нет. И что надо порождать новый объект?
ООП не занимается натягиванием концепций реального мира на программирования. Не выдумывайте чушь.
@@princessmary5556, конечно. ооп не занимается реальным миром вообще. ооп это всего лишь инструмент управления императивным кодом. и программистами императивного кода.
@@princessmary5556 Он не выдумывает, он повторяет азы любого учебника по ООП.
Статические методы служат общим для классов задач. Например, вы не будет в каждый класс вносить метод отправки данных по электронной почте.Статические методы также оформлены в класс статический. Программирование не должно быть ни функциональным, ни только ООП. И мыслить в соответствии с решаемой задачей. ООП позволяет сложный очень сложный код представить в виде нескольких важных классов, смысл которых не меняется в процессе развития проекта. Развитие проекта сводится к развитию этих классов, причем когда вы развиваете один класс это ни как не затрагивает другие классы. Беда начинается когда классов слишком много и смысл их плохо определен. Язык может быть любым, но если в нем нет реализации парадигмы ООП, то ее придется создавать. Получится функциональное программирование. ООП это развитие функционального подхода. Если вам трудно в ООП парадигме, то вам нужно менять мышление прежде всего. Автор лекции об этом говорит тоже. Но с тезисом о том, что классов должно быть много, я не согласен. Если их много они не неизбежно будут дублировать себя, это создает путаницу . Когда много похожих классов, то вы неизбежно начнете их путать, тем более чем менее вы автор исходника. Смысл каждого класса должен быть явным и глобальным, отличаться сутью объектов.
Докладчик говорить хорошие вещи, но, к сожалению, языком ошибся. В том же Rust работает как часы.
Что-то странное...
Критикуя ООП - топит за функциональное программирование)
5:06 Потому что, первое, объекты объектами, но в нормальном, не экспериментальном коде требуется оптимизация, а она с трудом возможна без процедурного подхода (без понимания процедур, тех процессов, которые стоят за всем). Недаром наиболее производительный софт писался и пишется на Си. В результате получается, программист должен мыслить одновременно и объектами, и процедурами. Второе, отсутствие нормального, единогласного, общепринятого, прозрачного объяснения основ. Нигде нормально не расскажут что такое инкапсуляция и полиморфизм, зачем они нужны в ООП, и почему ООП без них невозможно. Даже у апологетов противоречащее на сей счёт мнение. Касательно объектов, ООП это и то, что даёт инструменты программно описывать объекты, выделять участки кода, представляемые как объекты, и объектами является все в коде, любая буква. Это всё путает и грузит. Третье. Не только компьютер, и человек мыслит процедурно, особенно в том, что касается наук или каких-то навыков.
Да во всех букварях пишут вполне ясно и доступно, что такое инкапсуляция, и тп.
Амм,нет. Человек в наууах мыслит объектно с сохранением инвариантов бизнеса) матрица-объект,вектор-объект,алгебра -объект. Как то так.процедурно никакой науки нет.
похоже, спикер считает процедурнре и императивное программирование синонимами. процедурное - это всего лишь способ структурирования императивной программы. ровно как и объектно-ориентированное.
Статические методы не люблю, а вот статические инициализаторы - прикольно, впрочем Котлин решает этот момент.
Не согласен с Вашим отношением к Null На мой взгляд Null - величайшее изобретение, если Вы правильно понимаете суть. Null -это НЕЧТО, Потенциальная возможность реализации чего-либо, в то время как Ноль это НИЧТО, Пустое место Если помните Творец Создал НЕЧТО из НИЧЕГО То есть - Ноль это - Я Знаю что здесь пусто, а Null - Я Не знаю что здесь, пусто или нет, мне неизвестно. Как можно использовать в жизни: допустим Вам необходимо регулярно делать записи в таблицу, где есть обязательные параметры, например дата и текстовая запись, и ряд параметров классифицирующих и уточняющих эту запись. И эти параметры вы можете заполнять сразу если время позволяет, либо когда оно появится. Вот Вы открываете начатую запись и пытаетесь вспомнить, я в этом поле специально ноль или пустое место оставил, или я его ещё не заполнял? Это ведёт к лишним расходам Вашей психической энергии. А когда есть Null всё однозначно, значит это поле я ещё не заполнял, а нсли здесь ноль или пустая строка, то это было мной сделано намеренно. Не Важно, Прочерк.
Итог: чел 45 минут описывает принцип "Information expert" (GRASP). Как при таком подходе делать маленькие классы или следовать SRP - вопрос, который спикер опустил
Представляю объект: Егор егор = фабрикаЕгоров.дайЕгора(); егор.читай();
Егор читающийЕгор = егор.читай(); //вернет новый объект т.к. у Е*ора дрочь на иммутабельность всего и вся
34:45 - вот вся суть лекции в 1 предложении. И суть просто в том чтобы одно заменить на другое.
Ну т.е. вы не поняли суть.
Другое одно заменить на если, понятнее станет, длине же той при.
Зачем говорить, что "мыслить объектно" - это облегчение для программиста, если практика оказывается показывает, что для программиста естественно мыслить процедурами и программисты даже используя ООП все равно применяют процедурное мышление? Может надо перестать слепо верить в то, что объектно-ориентированный подход дает какие-то преимущества? И просто работать по улучшению методик и практик процедурного программирования?
Правильно. Писать надо так как проще. Так как мыслишь так и пиши. А не так как навязывают. Я как-то класс какой-то заумный из 1000 строк на php переписал на процедурный в виде 5 функций обычных и понятных и в итоге код занял около 300 строк. Скорость выполнения специально измерил - она абсолютно аналогична. Читаемость кода значительно улучшилась. И чего где какие преимущества? Просто крупные компании навязывают какие-то тенденции и все как дураки слепо идут в этом направлении.
Он еше на SCALA не писал :)
Ага, а если файл у нас в пару гигабайт, мы, наверное, хотим буферизованое чтение. И навернуть потом сверху «вернуть контент одной строкой». После чего вся концепция простого базового иммутабельного объекта рассыпается. Достаточно посмотреть на реализацию IO без прикрас, чтобы понять, что это не самые простые вещи. Кроме того, мне непонятно, что в таком случае делать с классическими задачами, которые мутабельности требуют - например, percolation, где у тебя может быть на входе двух или трехмерный массив на мегабайт, в котором клеточки открываются, и с каждой клеточкой нужно чекать, соединились ли грани. Каждый раз генерить новую карту на мегабайт? Удачи с 10к изменений массива. Реализовывать STM отдельно по каждому поводу? Затрахаетесь. Объясните, умные люди?
Чёткие мысли. На самом деле со временем начинаешь понимать их глубину. По первости я помню не мог со многим согласится...Прошли годы, набились шишки, книжки прочитались - и да, чистый красивый код родом отсюда будет)
Единственный момент, какой нибудь проэкт со стандартным подходом с гетерами сетерами и тд притом не говнокодя, а и менно качественно использывая стандартный подход, команда сделает за год, а , с данной философией эта же комманда затратит минимум в двое больше времени и везде в целом перформанс будет хуже чучуть или намного, а количество декораторов и оберток будет многие дестяки относящиеся посути к одной сущности, что поитогу приведет еще и к более худшей читабельности, точнее сказать удобству использовния, - да все будет понятно, но накой нам десятки оберток на сущность когда в ней можно иметь стандартно ее методы и удобно их просмотреть и заюзать когда нужно. Да обертки это круто и они нужны , но делать обертки хорошо также структурируяе по какой-то обобщенной расширяющей идеей, а не чуть ли не отдельная обертка на каждый метод... Корчое идея звучит очень красиво и рамнтично, но бизнесс реальность и прикладное использование будет щекотать вас своими клешнеми при использовании такого подхода.. Но звучит действительно красиво.
Ну так он и говорит, что это сделать сложнее, но сам проект в этом случае будет чище и в нем будет проще разобраться. Проще осознать кучу маленьких вещей, чем 1 большую. Ну и как вы замечаете, да действительно будет куча декораторов и связей между классами, но зато это будет нормальная форма, вы тут говорите не об объектах, а о структурах, в этом вся разница. И в случае структур, да мы хотим их изменять, но в таком случае, мы должны отдавать себе отчет в том, а что с ними происходит и мы спускаемся как спикер и замечает на нижний уровень, мы начинаем не доверять структуре, а следить за ней из-за этого и проявляются сложности. Ну вот изменив расположение файла, а откуда ты знаешь, что там еще получится, ты должен в голове держать, что там будет какой-то набор проверок, которые как-то взаимодействуют между другими компонентами что провоцирует к непредвиденным случаям. Ну и еще про реальный бизнес, как я слышал, тенденция имеется к распилу огромных монолитов на микросервисы, разумных масштабов, это же по сути и есть движение к этому подходу, просто надо найти четкую середину, в которой это имеет место быть.
Ну хз пример в виде глобальной константы строкового типа, как то не убедил что это трушный объект
Мясников, только в IT.
Покажите ему javascript
Удивишься, но на js можно писать вполне себе ООП, о котором говорит Егор. Просто кодер и программист -- это разные профессии.
@@user-ym2gd8kh2c ООП даже на ассемблере можно писать. Главное --- создать абстракцию геттеров и сетторов, чтобы потом их не использовать.
@@user-ym2gd8kh2c Можно. Но не нужно.
Блин бред, геттер это не только тупой возврат данных, возможно преобразование или возврат клона поля класса. По поводу сеттера, да, можно тут согласиться, возможно обойтись конструктором. В общем концепция разбиения предложенная автором понятна.
Если возможно преобразование, то это уже не геттер, а просто метод, включающий бизнес-логику и возвращающий значение. Возврат же клона не имеет смысла, если все объекты иммутабельны.
@@zachemny скиньте, плз, источник, где написано, что геттер, возвращающий, например, составленный результат, - это уже не геттер
Я думаю многие вещи сейчас людьми воспринимаются адекватней. Все в итоге, как он говорит, так и пытаются писать. Скала, например.
Скала появилась за 11 лет до этого доклада
Много всего правильного и очевидного. Про геттеры какая то притянутая за уши проблема, ну не нравится что кто то может использовать данные извне, ну не ставь ты public, а класс , который использует эти данные снаружи и очевидно, снимает часть нагрузки с нашего File - положи в тот же пекедж. Про сеттеры, они точно также как и геттеры позволяют "сломать" объект, иммутабл объектов не так уж много, соответственно get точно также как и set позволяет сломать. Ну либо отдаем всегда копию, как Блох завещал.
Рыцарь холивара
Object Oriented Programming is an expensive disaster which must end
Если я правильно понял автора, то так как он говорит я делать никогда не буду. Уж лучше я останусь в процедурах и функциях.
Правильно. Функциональное программирование -- это наше все.
Язык "с" по прежнему на вершине популярности, как и был за долго до вашего знакомства с программированием)
ПроГер - ПоСредник Между КоДером И ЛоГером! Их ПротивоРечия - Его Проблемы!
Чушь полная. Геттеры и сеттеры существуют не для того, чтобы делать из приватных свойств публичные, а для связывания данных, чтобы изменив одно свойство изменить и зависимые. Вы прочитали файл и можете получить его содержимое, но для того, чтобы узнать свойство (такое как путь) должны городить обвязку вокруг этого объекта, вместо того, чтобы запросить его у самого объекта.
но в таком случае, зачем ты создал файл? Ты создаешь файл, чтобы сделать с ним что-то конкретное, например, как тут показано, получить его контент. Если тебе нужен путь к файлу, то ты передаешь путь к файлу, тебе не нужен файл.
@@daiske2867 А если ты создаёшь список файлов? Тебе нужно содержимое для превью и путь.
34:00 Придёт Оккам - отрежет ядра.
Не понимаю помешанность на иммутабельности. Есть действительно подходящие ситуации. Есть не слишком. Как мне быть с той же машиной в момент езды? При каждом изменении угла, на которое повернулось колесо, создавать новую машину? Или колесо новое создавать? Это ни как не коррелируется с реальным миром. В реальном мире объекты не плодятся при изменении своего состояния. И состояние их меняется постоянно... А если машина состоит из большого количества деталей, то все они изменяют свое состояние и я постоянно буду вынужден проходить нехилый такой цикл инициализации машины. Ясно же, что это правило годится только для атомарных объектов как файл или объект даты...
так про то и речь, автор взял частный случай и пытается из него вывести общее, классическая демагогия
автор говорит, что у машины есть намного меньше свойств, чем вы ей приписываете. Машина может иметь например цвет или раму с колесами, а если вы поменяли раму с колесами на раму с гусеницами, то это уже другой объект будет. А в случае с поворотом колеса - то для этого будут меняться состояния объекта рулевого колеса, например, машина при этом не меняется, колесо тоже не меняется - оно как было колесом, так и осталось.
Философ доморощенный
Но статические методы и поля находятся в отдельном объекте, пускай его и представляют как "методы и поля вне объекта" - в Java все является объектом. Просто после загрузки класса мы имеет на старте уже один объект, хотя можем его не определять и объект будет пустой. А с геттерами и сеттерами я соглашусь на все 100%
Если правильно использовать статические поля и методы, то концепция ООП не теряется
Краткое резюме. Раньше существовали процедурные гитары, вы двигали руками и пальцами и думали как гитара и всю ответственность за производимую музыку брали на себя. А ООП гитара это новый шаг и новое мышлнгие - нажимаешь кнопку сыграй "звезду по имени солнце" и гитара сама играет. Ваши пальцы не могут нарушить инкапсуляцию и вмешаться в производимую мелодию. Вопрос из аудитории. А если я хочу сыграть "дождь идет с утра"? Ответ - тогда вы создаете новый класс, который ответственен только за игру "дождь идет с утра".
Если у нас уже есть класс, который умеет проигрывать музыку (например: "звезду"), то зачем нам ещё один класс для проигрывания "дождя" ? С технической точки зрения, песня "дождь" ничем принципиально не отличается от "звезды", это просто разные комбинации аккордов. В чем смысл создания ещё одного проигрывателя?
ну вы мыслите слишком узколобо, вы говорите о гитареИграющейЗвездуПоИмениСолнце, но гитара имеет метод сыграть мелодию, получает на вход мелодию и играет ее, а уже мелодия является такой-какой мы ее создать хотим хоть "звезда", хоть "дождь", хоть "сигареты"
Понятно
С каких пор инкапсуляция это "сокрытие"?
Ни с каких. Сокрытие скрывает, инкапсуляция - инкапсулирует. Это как бы принципиально разные вещи.
Ооп ради ооп. А Профит то где? Поддерживать сложнее, разрабатывать сложнее. Кало-кода ещё больше будет, если следовать подходу автора. Теперь вместо одного сервисного класса заведем два десятка фасадов.
вся парадима ооп - это именно о профите. инструмент бизнеса для интенсификации разработок за счет глубочайших компромиссов и костылей.
ООП это как конструктор лего, где детали либо похожи либо одинаковы. Много для чего подойдет. Но для реального творчества и произведений IT искусства нужна глина тонкого помола с мельчайшими частицами, а не конструктор. Но для очень крупных проектов конструктор лего будет той самой глиной, потому как размеры проекта этом случае гигантские. Вот и все что нужно знать про ООП. Если проект небольшой, содержит 10 функций, то никакого смысла вообще в классах нет.
@@KKZ_5000_RUB вы говорите не об ооп, а о библиотеках, модулях, классах и интерфейсах. но это не ооп а способы структуризации кода, используемые во всех парадигмах. ооп это всего лишь методы, которые могут хранить состояния, или состояния с определенным поведением. всё остальное (включая классы и интерфейсы) - это только полки, на которые можно разложить эти методы, и к сути ооп не относится.
ООП - это просто один из способов связать данные с кодом, который завязан на эти данные. И всё. Ничего лишнего. Причем в разных языках эта идея реализована разными способами, со своими особенностями и костылями Например в одних языках есть структуры данных и процедуры. Хочешь поменять структуру - вызови процедуру и передай в нее структуру: doSome(struct, data) В других языках решили организовать это в виде ООП, но не переусложнять, и появились составные классы, появилось понятие контекста, this. Процедуры теперь сгруппированы по неймспейсам, по классам, но это все ещё старые-добрые процедуры, и чтобы изменить в них структуру, ее туда нужно явно передать, в аргументе, написать код вида class.doSome(object, data) А сами структуры, чтобы связать их с классом, стали складывать в анонимные переменные, которые маппят под капотом на какую-нибудь заранее определённую переменную, такую как this или self. И вот мы уже имеем внутри класса странного вида вызовы, типа class.doSome(self, data), чтобы связать процедуры с контекстом, со структурой данных, которая содержит состояние объекта Ну а в третьих языках решили сдобрить все это синтаксическим сахаром, и спрятали this и self под капотом. При этом под капотом там все также отдельно структуры данных, отвечающие за состояние объекта, и отдельно структура данных, отвечающая за группировку процедур по классам, и в эти процедуры все также передается этот самый self, только теперь это происходит неявно, под капотом, и увидеть это можно лишь разбирая низкоуровневый код, который и работает под капотом языка и сокрыт за всем этим синтаксическим сахаром. И вот у нас появились вызовы вида object.doSome() И по итогу получается что у нас есть процедурный подход, и есть несколько реализаций ООП подхода, но по факту все это оказывается одно и тоже, просто в одном случае все это работает явно, а в другом неявно И выходит спорят люди просто из-за разницы в способе организации хранения процедур: в одном случае их хранят с обязательной группировкой по отдельным файлам, а в другом - с необязательной 😂
связать данные с кодом, который завязан на эти данные 🤔. больше поже на определение хард-кода.
NULL - читается "нал", а не "нул"
Как возможно геттером изменить неизменяемую стрингу?
Да легко, replace() например
@@user-sy6jp7wd8y Он создаст и вернет новую стрингу. Но никак не изменит ту, на которой replace() был вызван.
@@vh3104 точняк) спасибо что поправили)
Это ж очевидные вещи, их любой студент знает. Чего тут на час рассусоливать ? То, что геттеры и сеттеры - зло и надо скрывать реализацию - это называется инкапсуляция, одна из основополагающих вещей в ООП.
Почему это геттеры/сеттеры - зло?
@@princessmary5556 потому что чаще всего они ничего не делают вообще, что люди аж ломбок придумали, не понимая зачем писать лишние строки кода
@@ALIKRUNOV Бред.
Геттеры и сеттеры - это как раз и есть элемент инкапсуляции.
@@alexperemey6046 геттеры и сеттеры это элемент нарушения инкапсуляции. Судя по комментариям, большинство комментаторов не видели больших проектов и не понимают к чему приводит бездумное и корректное использование принципов и паттернов ООП.
Классы - те же функции, просто создатели java решили "выпендрится". ООП дискредетировала себя - код стал более нечитаемым, особенно, в крупных проектах. До сих пор в космической отрасли и связи используется модула-2 (1970 года), как самое надежное средство.
"До сих пор в космической отрасли и связи используется модула-2 (1970 года), как самое надежное средство." Согласен. Нам "продают" чей-то опыт в программировании и заставляют этот опыт воспроизводить, и называют это "культурой программирования".
Абсолютно верно. Классы эти - полная туфта. Как и код на 100 000 строк. Замучаешься в таком коде ошибки искать. Все должно быть просто и понятно. На php допустим вообще классы не нужны. Проще разбить код на несколько файлов небольших, вместо класса будет отдельный файл-обработчик. Тогда и дебажить намного проще и если вдруг случайно потрешь код какой-то то не так много восстанавливать. Длинные файлы это вообще хрень по опыту могу сказать. А в коротких и никакие классы не нужны. Пиши обычными функциями да и все, чё там мудрить то. С классами этими куча кода лишнего и ненужного получается. Короче туфта. Которую придумали в крупных компаниях, а мелкие выпендриваются и хотят соотвествовать их "стандартам". А на практике все это не неудобно, не читаемо, сложно искать ошибку, просто случайно навредить и т.д.
В момент, когда Егор показал "правильный" класс Файл с методом "контент", почему-то вспомнилась сценка Уральских пельменей про что-где-когда - Гладиолус. Ну серьёзно.. вроде как название метода должно однозначно обозначать его действие. Что за название такое "контент"? Минуту назад утверждалось что то там про геттеры.. И тут такой хуяк.. - метод "контент". Ну круто, чё.
А как должно быть?
@@user-sy6jp7wd8y getContent же :)
Объекты как раз и есть структуры с приаттачеными к ним функциями-методами. Во всяком случае, это так на бинарном уровне в таких языках как C++, C#, Java и многих других. И не более того. Наличие рефлексии и виртуальных и прочих таблиц, связанных с классом, в этом плане ничего не меняет. В таких языках, как Smalltalk и Erlang - возможно, это не так, точно не скажу. Но если говорить о мэйнстриме программирования, то никакой волшебной жизни, как утверждает автор, в объектах нет, никакими сообщениями они не обмениваются и никакого тайного смысла не несут. Просто нет соотв. этому механик в самом ЯП и в платформе. И инженер должен это чётко понимать, а иначе программирование превращается в какой-то мистицизм или карго-культ. С соотв. результатами.
Капитан Очевидность
Боже! Куда скатилось IT! Уровень докладчика и большинства комментаторов ниже плинтуса... Единственное, на что уповаю - здесь практически нет серьезных разработчиков 😕
Есть серьезные. А что конкретно вам не нравится? ООП это как конструктор лего, где детали либо похожи либо одинаковы. Много для чего подойдет. Но для реального творчества и произведений IT искусства нужна глина тонкого помола с мельчайшими частицами, а не конструктор. Но для очень крупных проектов конструктор лего будет той самой глиной, потому как размеры проекта этом случае гигантские. Вот и все что нужно знать про ООП. Если проект небольшой, содержит 10 функций, то никакого смысла вообще в классах нет.
Глупее доклада не видел. Начиная с того, что автор явно сам не понимает что такое объект, если говорит, что это набор данных с "прикрепленными" функциями. Это и есть "нечто живое со своим поведением". Перед докладом стоит читать книги, а не придумывать свои "велосипеды". Автор максимально далеко от понимания ООПа и нормального кода и, тем более, его работы. Не удивлюсь, если за этой фигурой нет ни одного серьезного проекта(( Печально, если кто-то впитает это демоническую чушь. Это даже на уровне джуна звучит очень примитивно.... Даже на простейшем геттере ничего не понимает. Прототип айтишной Бузовой. Вначале лекции иметь геттеры плохо))) Зато декоратор, который может брать что-то из файла - хорошо, хотя это то же геттер. Такими шагами программисты лет 30-40 назад двигались)))) Мужик сам себе противоречит)))) Кличка - "монолитер"))))
Ну, то есть, этот доклад про то, что этот бумер не понял, что такое интерфейс и не был в состоянии абстрагироваться от конкретных классов. Принципы ООП? Инкапсуляция? Полиморфизм? Наследование? Абстракция? Он не просто не слышал об этом (хотя это, сцук, на каждом собесе спрашивают. Как он вообще кодил то до этого?), он еще уверен, что НИКТО об этом не слышал. То, что геттеры и сеттеры могут быть абстрактной частью интерфейса он, видимо, тоже не понимает. Бумер не читал ГОФов (иначе он бы знал, что такое инкапсуляция), но говорит, что их паттерны не ООПешные. Бумер не в состоянии понять, что такое свойство и считает, что класс File не должен иметь getPath. Как бы бумер офигел о задачи взять множество файлов и взять их директорию и расширения с таким подходом... Бумер не понимает, что абсолютная иммутабельность недостижима. И даже в Haskell абсолютной иммутабельности нет. А как бы он офигел, если бы столкнулся с задачей изменения содержимого директории в два потока. Говоря о паттернах: бумер не знает, что такое билдер и считает, что сложных объектов быть вообще не должно и у нас должен быть один слой абстракции с 100500 объектами. Бумер не понимает, как это main-функция является статической и не принадлежит объекту в куче. В какой то момент бумер в открытую говорит, что ООП не нужно. Нужно упоротое подобие ООП, где объекты - это GodObject'ы, а вся их функциональность завернута в декораторах. О том, что декораторы не относятся к ООП, а в С++ их нет вообще, бумер не в курсах. Ребята кидались в него умными мыслями, но он ловко уворачивается. Как этот мужик вообще в IT оказался?
top !!
Удивительно, где ты вообще это всё услышал? "Бумер не в состоянии понять, что такое свойство и считает, что класс File не должен иметь getPath" - уже здесь понятно, что ты не отличаешь свойство объекта от геттера и не понимаешь, что такое инкапсуляция. А дальше рассуждать нет смысла...
бумер != этот мужик. Просто именно этот мужик упорот.
Егор снова проталкивает зрителю надуманную проблему и пытается лечить симптом, а не причину. В основе проблемы лежат именно рассмотренные языки (java, c++), а фреймворки и утилитные библиотеки делают жизнь проще и легче. Я б рекоммендовал Егору написать хотя б один коммерческий заказ на джаве без фреймворков и утилитных библиотек, там разум быстро б стал на правильное место. Если будет ответ что так и делал - видео в студию, я реализую то же с ходу в разы быстрее с использованием фреймворков. Потом если с фреймворками получается мусор в коде, что ж с твоим кодом будет без фреймворков? А може Егору стоило б вспомнить как код пишется для начала?
он свой фрейморк написал и у него свои проэкты на этом фреймворке... по крайней мере так было лет этак назад
Да, это боль
Автор вообще сам код пишет или только балабол? Если бы писал, то херню бы не проповедовал.
ну знаешь нет лучше всего о вреде курения может рассказать только человек, который курит и он вероятно шишек достаточно навыбивал, раз синтезировал именно в такой форме, например анализируя проблемы, с которыми он зачастую борется.
Вероятно видео должно было называться: ООП - Объектно-Ориентированый Пиздеж
ядрена мать! эту лекцию можно спроецировать не только на программирование!
Докладчик пытается изо всех сил притворяться, что данных не существует, и пытаться писать программу так, будто есть только поведение, а данных нет. Именно поэтому сферическое ООП в вакууме, которое он проповедует, так и не вылезло из песочницы, ведь за её пределами данные и способы работы с ними игнорировать невозможно, а в распределённых системах они и вовсе выходят на самый первый план. Способы разбиения данных, компромиссы CAP, как мы будем разруливать неизбежные конфликты и partial failures - вот о чём болит (или должна болеть) голова у стоящих разрабов. А не о том как пообъектнее изобразить живой объект комментарий который умеет себя редактировать. Тьфу.
вы путаете архитектуру и реализацию. В вашем примере "стоящие разрабы" должны заниматься написанием алгоритма, а в видео речь об архитектуре проекта, которая неизбежно скатывается в уг из-за непонимания, как вообще ее строить. Тьфу (с)
partial - антипаттерн
@@acd2377 да, конечно же мы можем измерить габариты табуретки. Вопрос геттеров больше философско-концептуальный, чем имеющий практичное значение. Вреда от геттеров немного, но обычно они указывают на "код-смелл". Вам вдруг зачем-то понадобились параметры табуретки вместо того, чтоб взять и сесть на неё. Потому что объект табуретка создается для того, чтобы на нем сидеть. А если вам нужны габариты табуретки -- то вам стоит спросить их у объекта "столяр", который построил табуретку и знает её структуру. А не у самой табуретки. В общем, если вы разговариваете с табуреткой -- в вашей жизни и вашем коде, что то определенно идёт не туда. Вот как бы вкратце о геттерах, но повторюсь, что все эти принципы не могут быть строго формализированы и просто следует воспринимать как указания. Есть где-то геттер -- посмотреть, а действительно ли он нужен, и зачем внешнему объекту понадобились внутренние данные другого объекта, возможно внешний объект делает работу, которую должен делать не он, а запрашиваемый объект. С сеттерами все сложнее и интереснее. Да, как бы это дико не звучало -- нужно выбросить старую табуретку и купить новую с другим цветом. Представьте себе, что табуретки в магазине по три на рубль, и для вас это финансово вообще не проблема. Но логичный вопрос - - почему нельзя перекрасить? И тут уже надо понимать почему у Егора текут слюни на иммутабельные объекты. А все потому, что они очень удобны и надёжные. В примере с табуреткой -- у вас есть табуретка черного цвета и в любой момент времени, разбуди вас в три часа ночи в воскресенье под дулом пистолета и спроси какой цвет у табуретки -- вы без тени сомнения ответите что чёрный. И будете правы на 100% и всегда, и во веки веков, аминь! Чего нельзя сказать о мутабельной табуретке с сеттерами. Вы никогда не знаете, а не покрасил ли её сосед, пока вас дома не было. Вы приходите домой, ничего не подозревая, с разгону садитесь на свежепокрашенную табуретку и у вас вся ж...э-м-м.. седалищная часть брюк теперь ярко красного цвета. Вот чем плохи мутабельные объекты. Вы никогда не уверены в них на 100% и должны проверять "иф (табуретка не крашена") { сесть на таберутку } елзе { ждать пока высохнет краска }.
@@acd2377 "Модель мира" и "доминация" это лишь для красного словца. В действительности неудачные аналогии только вносят дополнительную неразбериху. Я просто отсеиваю их сразу и рассматриваю только практическую сторону вопроса -- чем мне это облегчит жизнь как программисту. Геттеры и сеттеры плохи именно с практической точки зрения. (Хотя это и странно выглядит поначалу.) А вся философия - это шелуха.
@@acd2377 Понятие "модель объекта реального мира" означает упрощенный вариант - имитацию некоторых свойств объекта реального мира. Думаю суть иммутабельных объектов в моделировании только нужных свойств, избавлении от ненужных состояний и лишней сложности из-за этого (Сложность от бесконечного числа классов, видимо, не учитываем). Получается при инстанцировании объекта табуретки мы создаем спроектированную в классе модель табуретки из реального мира. И этих моделей можно создавать сколько угодно с любыми свойствами в любой момент времени. Это наша виртуальная модель любой табуретки из любой точки пространства-времени реального мира. Например, увидели вы табуретку голубого цвета - у вас в сознании создалась модель иммутабельной голубой табуретки, затем вы посмотрели на табуретку желтого цвета - аналогично и с ней.
Егор, отличная лекция о "философии на пальцах", продолжайте в том же духе! И разработчики java не смогут игнорировать такую статистику, и улучшат её))
За смелость мысли лайк. По поводу объекта согласен
Какие тонкие материи, спасибо!