Удобно не реализовывать полностью интерфейс и конструктор сделать пустым и однострочным, что еще удалили?
И это на элементарном примере, заточенном для "У вас это не получится. В этом был весь смысл примера с кодеками."
Вы согласились написать полный пример для демонстрации вашего процедурного подхода? Согласились.
Я согласился переписать ваш код на ФП, что без проблем сделал. Про процедурный подход это вообще ваша выдумка - в статье ясно говорится в начале что такое ФП и ПП, и статья про ФП.
Ну попробуйте заменить swEncoder.requestKeyFrame() на вызов процедуры. У вас это не получится. В этом был весь смысл примера с кодеками.
Я ее заменил на вызов функции, без классов и без проблем из статьи. Хотя даже и на вызов процедуры заменить не проблема, и самое смешное что вы далее сами это делаете. Не зря статью читали (с).
Глобальные функции можно вызывать и с ООП
Во-первых функция может быть необязательно глобальная, а создана в функции конструкторе или еще где то.
Во-вторых, я рад что вы в итоге пришли к ФП и когда нужно сделать что то гибко и просто - будете его использовать, вызывая глобальные функции. Жаль только не во всех языках это можно делать, и придется создавать нетестируемые статические классы.
User.getDisplayName() из вашего примера в статье. У него тоже нет ссылок на другие методы,
Вы видимо таки не поняли о чем речь, попробую объяснить еще проще: this - это объект класса где есть все из этого класса. А значит метод жестов завязан на тип этого класса, и его нельзя переиспользовать для данных, у которых нет всего, что есть в this. То есть если в User есть метод goFckYourself, то чтобы переисолзовать getDisplayName из User нужно будет добавить в мои данные, например Dog, этот же метод, иначе никак. Более того, единственный способ их добавить это отнаследовать Doc от User, добавив таки эти методы. Надеюсь теперь понятно, если нет - тут уже ничем не помогу.
Это можно сделать и с ООП, но вы в статье все равно это указали как проблему ООП.
В статье речь про то, что в методах класса выбора нет, а в ФП выбор есть, и даже пример есть с getDisplayName - советую почитать еще раз.
В итоге ни одно ваше утверждение не доказано, ни про "у вас это не получится", ни про "у метода нет ссылок на другие методы", ни то что можно сделать this опциональным в ООП, и даже переписать на классы JS без читинга ваш собственный, якобы заточенный на превосходство ООП пример.
Полный провал.
Но хотя бы пришли к тому, что в С++ тоже можно использовать процедуры если нужно гибко и просто. Хоть что то хорошее.
PS. Сложность кода оценивается не только строчками, а в том числе количеством символов языка (типа class со всеми вытекающими из них this, наследованием, модификаторами доступа и тп), багоемкостью (типа попытки передать метода класса как параметр, получая вместо this undefined) и прочими проблемами, перечисленными в статье. Тут у вас тоже полный провал.
Все различия связаны с синтаксисом языков JavaScript/CPP
Нет, в JS тоже есть классы и вся эта ерундистика. Я использовал более лаконичный и простой подход без лишних символов. И по сторчкам, и в целом по символам вышло меньше. Даже на специально выбранном вами примере и с точно таким же подходом без особого рефакторинг.
Методы encode и requestKeyFrame в вашей реализации тоже приколочены к this. Например если вы захотите вызывать один метод из другого, вы будете использовать this
Они вообще никуда не приколочены и там нет ни одного символа this.
Более того у стрелочных функций что я использую в принципе нет this.
Этот пример полная копия вашего, только без классов.
Эти функции можно без проблем вынести в процедуры если возникнет такая необходимость, например:
// Аргументы только те, что используются, ничего лишнего
const encodeVp9S = (frame: Frame) => {
// ...
}
const makeVp9SWEncoder = (): Encoder => ({
encode: encodeVp9S
});
У вас эти методы зависят даже не от класса, а вообще от конкретного объекта.
Ограничений здесь нет, см. пред. пример.
У вас то же самое, методы encode и requestKeyFrame "требуют для работы" все методы, которые есть в объекте где они объявлены.
Опять ошибка - где они это требуют? У них даже ссылки нет друг на друга))
У вас аналогично, нельзя использовать метод без создания объекта где он содержится.
И тут ошибка - если нужно то можно - см. пред. пример.
Сможете обработать в ваших методах ситуацию, когда encoder null или undefined? Я в этом сомневаюсь.
То что можно функцию разбить на несколько функций это называется обычный рефакторинг. Если код слишком простой - нет смысла городить абстракции, если начинает усложняться то смысл появляется.
Правильно. А если больше, то хуже. В вашем коде проблем больше.
Я бы вам ткнул пальцем,
Ключевые слова "я бы". Я думаю можно этими двумя словами подытожить все потуги ООПшников))
Я все проблемы ООП, перечисленные в статье, не реализовывал в своих примерах - и их там нет. А если, как вы заявляете, код очень похож, но в одном из вариантов сильно меньше проблем чем во втором - значит он лучше.
Если это был типа "плохой" пример, то надо учиться яснее общаться. Второй ваш пример это вообще непонятно что на вашем фреймворке, в котором 1) я разбираться не имею никакого желания 2) вообще не ясно как массив редактируется и как используется, и почему у игрушки зачем то есть count().
Если вы топите за мутабельное состояние [от которого проблем часто больше, при схожей производительности], то вот простейший пример вообще без фреймворков:
Можно было бы вынести повторяющиеся паттерны в отдельный фреймворк, либо использовать готовые решения, но суть в том, что это все прекрасно реализуется в ФП.
Я привел аж три способа реализации полиморфизма (union type, обобщение и интерфейс), и даже указал в каких случаях их лучше использовать, и даже реализовал где то здесь в комментариях код на обобщениях, который якобы "нельзя реализовать на ФП".
Вот фраза из статьи, с дальнейшими примерами кода:
Далее в примере для этого будут использоваться union type, обобщение и интерфейс:
Я только и делаю, что пишу большие системы с абстракциями, и как я уже говорил, сейчас практически все сайты, в тч самые сложные и высоконагруженные, пишутся в парадигме ФП, если вы не знали.
Во-первых ООП в моем видении, описаном в статье, в приведенном коде отсутствует. Это просто псевдо-декларативное описание модели и поведения, на основе которой генерируется ООП код, а мог бы генерироваться и ФП с тем же "успехом".
Почему псевдо - потому что если слишком много логики запихнуть в декларативность, то как работает код поймет только его автор [и Майкл Джексон]. Так же он будет обладать большим количеством ограничений, на который наткнешься уже по факту, и чтоб от них избавиться придется все переписывать. И чтобы реализовать даже простейшую задачу, придется очень долго и нудно читать документацию этого фреймворка. Поэтому ваш фреймворк обречен, к сожалению.
Другими словами, вы не выполнили главное требование инженера - чем проще, тем лучше.
Вот как выглядит хороший, простой код (псевдокод) на функциях:
// Модель отделена от логики
type User = {
id: number
name?: string
description?: string
created_at?: number
avatarUrl?: string
hobbies?: string
}
// Хранение состояния отделено от UI и слоя доступа к данным.
// Здесь мог бы быть любой стор - мутабельный, иммутабельный, на прокси или евент емиттерах и тп.
type EntitiesState = {
users: User[]
userConfigs: UserConfig[]
}
const entitiesStore = create<EntitiesState>({
users: [],
userConfigs: [],
})
// Бизнес логика.
const changeUserConfig: (userConfig: Partial<UserConfig> & Pick<UserConfig, "id">) => {
// Меняем значение в entitiesStore.
}
// UI - любая библиотека на усмотрение.
const UserPage = ({id}: {id: string}) => {
const user = useEntitiesStore((state) => selectUser(state, id))
if (!user) return <Loader />
return (
<Html>
<Title value={user.name} />
<Description value={user.description} />
// ...
</Html>
)
}
Если приведете более конкретный пример кода, который надо реализовать, я вам напишу как. Главное только чтобы это было не ограничение заточенного под ООП языка.
Если хотелось реализовать мемоизированное вычисляемое состояние, то это делается элементарно в каком нибудь zustand / redux через reselect, если устраивает иммутабельный стор, если не устраивает есть и мутабельные сторы в парадигме ФП.
Более того, можно хоть на ивент еммитерах это реализовать если нужна супер произвотидельность.
Но самое смешное что даже RX из ваших примеров можно использовать в парадигме ФП, и первый кусок кода в ней и написан, если не считать создание BehaviorSubject через new, который мог бы создаваться через функцию make*.
Вот код что сгенерировал GPT, я не проверял но плюс минус то же самое но без классов - меньше, понятнее и без проблем из статьи:
Удобно не реализовывать полностью интерфейс и конструктор сделать пустым и однострочным, что еще удалили?
И это на элементарном примере, заточенном для "У вас это не получится. В этом был весь смысл примера с кодеками."
Я согласился переписать ваш код на ФП, что без проблем сделал. Про процедурный подход это вообще ваша выдумка - в статье ясно говорится в начале что такое ФП и ПП, и статья про ФП.
Я ее заменил на вызов функции, без классов и без проблем из статьи. Хотя даже и на вызов процедуры заменить не проблема, и самое смешное что вы далее сами это делаете. Не зря статью читали (с).
Во-первых функция может быть необязательно глобальная, а создана в функции конструкторе или еще где то.
Во-вторых, я рад что вы в итоге пришли к ФП и когда нужно сделать что то гибко и просто - будете его использовать, вызывая глобальные функции. Жаль только не во всех языках это можно делать, и придется создавать нетестируемые статические классы.
Вы видимо таки не поняли о чем речь, попробую объяснить еще проще: this - это объект класса где есть все из этого класса. А значит метод жестов завязан на тип этого класса, и его нельзя переиспользовать для данных, у которых нет всего, что есть в this. То есть если в User есть метод goFckYourself, то чтобы переисолзовать getDisplayName из User нужно будет добавить в мои данные, например Dog, этот же метод, иначе никак. Более того, единственный способ их добавить это отнаследовать Doc от User, добавив таки эти методы. Надеюсь теперь понятно, если нет - тут уже ничем не помогу.
В статье речь про то, что в методах класса выбора нет, а в ФП выбор есть, и даже пример есть с
getDisplayName
- советую почитать еще раз.В итоге ни одно ваше утверждение не доказано, ни про "у вас это не получится", ни про "у метода нет ссылок на другие методы", ни то что можно сделать this опциональным в ООП, и даже переписать на классы JS без читинга ваш собственный, якобы заточенный на превосходство ООП пример.
Полный провал.
Но хотя бы пришли к тому, что в С++ тоже можно использовать процедуры если нужно гибко и просто. Хоть что то хорошее.
PS. Сложность кода оценивается не только строчками, а в том числе количеством символов языка (типа class со всеми вытекающими из них this, наследованием, модификаторами доступа и тп), багоемкостью (типа попытки передать метода класса как параметр, получая вместо this undefined) и прочими проблемами, перечисленными в статье. Тут у вас тоже полный провал.
Нет, в JS тоже есть классы и вся эта ерундистика. Я использовал более лаконичный и простой подход без лишних символов. И по сторчкам, и в целом по символам вышло меньше. Даже на специально выбранном вами примере и с точно таким же подходом без особого рефакторинг.
Они вообще никуда не приколочены и там нет ни одного символа this.
Более того у стрелочных функций что я использую в принципе нет this.
Этот пример полная копия вашего, только без классов.
Эти функции можно без проблем вынести в процедуры если возникнет такая необходимость, например:
Ограничений здесь нет, см. пред. пример.
Опять ошибка - где они это требуют? У них даже ссылки нет друг на друга))
И тут ошибка - если нужно то можно - см. пред. пример.
А в замыкании ситуакция когда оно
null
невозможна.Итого, написанное калькой ваше же решение, которое лично я бы писал по другому, более лаконичное и не имеет никаких ограничений.
Какой то детский сад а не код)) Даже не буду рефакторить, выложу то же самое (78 строк).
Вы сами скинули ссылки на два куска кода, и плюс еще просите учесть свой кусок кода. У меня аналогичные куски кода.
Приведите сами ВЕСЬ код а не несколько кусков, потом поговорим.
Какой кусок кода нужно еще привести, чтобы вы смогли увидеть проблемы?)
И где ваш полный пример этого кода?)
То что можно функцию разбить на несколько функций это называется обычный рефакторинг. Если код слишком простой - нет смысла городить абстракции, если начинает усложняться то смысл появляется.
Ключевые слова "я бы". Я думаю можно этими двумя словами подытожить все потуги ООПшников))
В ФП с этим нет проблем - функция может пользоваться другой функцией, не зная конкретно что это за функция.
В вашем последнем куске кода тоже нет.
Я все проблемы ООП, перечисленные в статье, не реализовывал в своих примерах - и их там нет. А если, как вы заявляете, код очень похож, но в одном из вариантов сильно меньше проблем чем во втором - значит он лучше.
Он работает так же [плохо] как и в вашем примере.
Если это был типа "плохой" пример, то надо учиться яснее общаться. Второй ваш пример это вообще непонятно что на вашем фреймворке, в котором 1) я разбираться не имею никакого желания 2) вообще не ясно как массив редактируется и как используется, и почему у игрушки зачем то есть count().
Если вы топите за мутабельное состояние [от которого проблем часто больше, при схожей производительности], то вот простейший пример вообще без фреймворков:
Можно было бы вынести повторяющиеся паттерны в отдельный фреймворк, либо использовать готовые решения, но суть в том, что это все прекрасно реализуется в ФП.
Так статистику поищите и не сомневайтесь больше.
Как только хоть один человек скинет код, на котором будет видно, как забивать гвозди связанными скотчем костылями (ООП) лучше, чем молотком (ФП).
Я привел аж три способа реализации полиморфизма (union type, обобщение и интерфейс), и даже указал в каких случаях их лучше использовать, и даже реализовал где то здесь в комментариях код на обобщениях, который якобы "нельзя реализовать на ФП".
Вот фраза из статьи, с дальнейшими примерами кода:
Я только и делаю, что пишу большие системы с абстракциями, и как я уже говорил, сейчас практически все сайты, в тч самые сложные и высоконагруженные, пишутся в парадигме ФП, если вы не знали.
Вот пример мобильного приложения https://github.com/mattermost/mattermost-mobile. Там же есть и десктоп, и веб.
Вы не специалист, наконец то признали, тогда есть чему поучиться.
Во-первых ООП в моем видении, описаном в статье, в приведенном коде отсутствует. Это просто псевдо-декларативное описание модели и поведения, на основе которой генерируется ООП код, а мог бы генерироваться и ФП с тем же "успехом".
Почему псевдо - потому что если слишком много логики запихнуть в декларативность, то как работает код поймет только его автор [и Майкл Джексон]. Так же он будет обладать большим количеством ограничений, на который наткнешься уже по факту, и чтоб от них избавиться придется все переписывать. И чтобы реализовать даже простейшую задачу, придется очень долго и нудно читать документацию этого фреймворка. Поэтому ваш фреймворк обречен, к сожалению.
Другими словами, вы не выполнили главное требование инженера - чем проще, тем лучше.
Вот как выглядит хороший, простой код (псевдокод) на функциях:
Если приведете более конкретный пример кода, который надо реализовать, я вам напишу как. Главное только чтобы это было не ограничение заточенного под ООП языка.
Дождались наконец.
При чем тут процедурная?
Примеров все еще нет.
Если хотелось реализовать мемоизированное вычисляемое состояние, то это делается элементарно в каком нибудь zustand / redux через reselect, если устраивает иммутабельный стор, если не устраивает есть и мутабельные сторы в парадигме ФП.
Более того, можно хоть на ивент еммитерах это реализовать если нужна супер произвотидельность.
Но самое смешное что даже RX из ваших примеров можно использовать в парадигме ФП, и первый кусок кода в ней и написан, если не считать создание BehaviorSubject через new, который мог бы создаваться через функцию make*.
Вот код что сгенерировал GPT, я не проверял но плюс минус то же самое но без классов - меньше, понятнее и без проблем из статьи:
Поищите на маркетплейсах «мини-UV УФ стерилизатор для аквариума, С таймером Ультрафиолетовая аквариумная лампа, 3 Вт».
Если не пахнет значит часто моете)
У меня такая же, маленькая лампа влезла ровно под бак. Запах у воды с тех пор пропал.
Купите мойку, киньте ультрафиолетовую лампу для аквариумов - все.