LINUX.ORG.RU
ФорумTalks

Отрицательные составляющие ООП, что скажете?

 


0

2

Как-то читал статью функциональное программирование против ООП, где каждый высказывался в сторону своей парадигмы, сейчас вот опять наткнулся на отзыв об ООП. У меня начинает складываться впечатление что во первых в зависимости что писать, а во вторых как в музыке о вкусах не спорят.

В некоторых разработках объектно-ориентированное программирование отодвинуто на второй план, что уже было показано, поскольку оно потребляет слишком много памяти и ресурсов.

Накладные расходы на память: каждому объекту требуются метаданные для администрирования. Миллионы мелких объектов фрагментируют рабочую память (ОЗУ).

Промахи кэша ЦП: современные процессоры работают быстрее всего с линейными структурами данных (ориентированный на данные дизайн). ООП разбрасывает данные в памяти, что замедляет работу ЦП.

Проблема «банановой гориллы»: глубокие цепочки наследования часто заставляют разработчиков создавать огромные, ненужные родительские классы, хотя необходима лишь небольшая их часть.

Успешные альтернативы: современные языки, такие как Rust, Go или Zig, предпочитают композицию, простые структуры (Structs) и функциональный подход вместо жестких иерархий классов.



Последнее исправление: AZJIO (всего исправлений: 1)

Ты б хоть написал чего там.

Обычно претензии к ооп в том, что оно дает людям слишком много свободы, и они не могут ею распорядиться.

ya-betmen ★★★★★
()
Последнее исправление: ya-betmen (всего исправлений: 1)

в зависимости что писать

Не что, а с кем и для кого. Ваще там аргументы тот еще детский сад (а чего еще ожидать от бейсика):

Deep inheritance chains often force developers to provide huge, unnecessary parent classes, Although only a small part is needed

Нормальные люди пишут код для других людей, а не для компилятора. Конечно можно накопипастить, заинлайнить и обфусцировать так чтобы за умного приняли, но в здоровом коллективе (который у лоровцев считается легендой) главное это гибкость (сюда же поддерживаемость, нехрупкость, тестируемость и далее по канонам Мартина), а ООП этому чаще помогает, чем мешает. Выстрелить в ногу или наговнокодить можно где угодно и на любом языке, просто ООП дает ориентиры как этому помешать. Если пишешь хелловорды для себя, конечно, это все излишне.

В общем я нормальных отрицательных сторон так не увидел. Как будто очередные стартаперы комплексуют, что без ООП их взрослые дяди засмеют и придумывают отмазки. Хотя сами ни в хайлоаде, ни в бигдате не участвуют про их велосипеды разве что на лорчике узнаешь.

Lordwind ★★★★★
()
Последнее исправление: Lordwind (всего исправлений: 2)

ООП ненужен, бейсик ненужен тоже.

Nervous ★★★★★
()
Ответ на: комментарий от ya-betmen

Ты б хоть написал чего там.

Там школота рассуждает о программировании. ТС зачем-то это принёс на ЛОР.

seiken ★★★★★
()
Ответ на: комментарий от ya-betmen

Ты б хоть написал чего там.

Добавил перевод, хотя сам я сторонник читать оригинал. Ну да ладно, я же сам читаю через переводчик…

AZJIO
() автор топика
Ответ на: комментарий от AZJIO

Ну а что ты хочешь? По поводу того, что и почему сделано в го, можешь к срачу соседнему обратиться.

ya-betmen ★★★★★
()
Ответ на: комментарий от Lordwind

Как будто очередные стартаперы комплексуют, что без ООП их взрослые дяди засмеют и придумывают отмазки.

Автор поста имеет кучи функций виндос/линкус-совместимые (сетевые, гуишные и прочие), предлагает добавление модулей для линукс (протестировав его API), что могут обычно близкие к разработке языка. От вас я пока ничего не видел кроме слов. Вы так старательно скрываете свой код, что запрашивая много раз и столько же раз получаешь ничего.

Всё что ты можешь это ставить клоунов.

AZJIO
() автор топика
Последнее исправление: AZJIO (всего исправлений: 3)
Ответ на: комментарий от seiken

Если бы ты не был школотой, тебя бы не зацепило. Все кто чувствуют себя слегка обделёнными пытаются поплевать на других. Самодостаточный и заинтересованный и особенно трудяга у него даже времени не будет с кем то бороться на пустом и в кого-то покидать какашки, если не интересно пропускает. Нафиг тут на полстраницы запускать пусто-трёп и срач? Кому интересно кого я ищу, а что хочу обсудить я выше написал. Если нечего сказать необязательно лишь бы что-то написать.

AZJIO
() автор топика
Ответ на: комментарий от seiken

Чел по полочкам разложил недостатки ООП, такие мне нравятся, не надо 20 страниц читать, тестировать, когда чел уже сделал это и делится знаниями в лаконичной форме. Такие ответы часто днём с огнём в течении нескольких лет не сыщешь.

AZJIO
() автор топика
Ответ на: комментарий от seiken

Тебе гопота выложит все те аргументы по ссылке против ООП, и ещё тележку других.

Не не выдала… я погуглил термин «функциональное программирование», точнее вот прям дословный запрос «противовес ООП функциональное программирование», а чтобы проверить не ошибся ли я в термине и даже хотел нагуглить старую статью, ну и гугл выдал ИИ-шный текст практически не интересный, грубо говоря мусор, по сравнению с живым человеком специалистом.

AZJIO
() автор топика
Ответ на: комментарий от AZJIO

Стандартный ответ в таком случае: ты просто не так спрашивал.

seiken ★★★★★
()

Что за каша в голове у того, кто это писал? Композиция - такой же инструмент ООП, как и наследование. Тут не ООП против ФП в том же раст, а просто отказ от наследования - проблемы в нем, а не ООП в целом. ООП охрененный подход так то.

LightDiver ★★★★★
()
Ответ на: комментарий от AZJIO

ну и гугл выдал ИИ-шный текст практически не интересный

Ааа.. Если тебе надо интересно - почитай Пратчетта. Там 40+ книг. Очень интересно.

ООП это многогранная концепция - программирование, подход, оформление кода. Парадигма мышления в целом. Мы работаем с объектами. Это упрощает разработку, но и накладывает накладные расходы. Инкапсуляция и недетерминированность тут один из плюсов, особенностей.

ФП это детерминированность и прозрачность. И повышение сложности разработки на порядок. Для человека.

Не кидайся в крайности. ООП для организации, фп для логики и данных. Каждому инструменту свое место.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 1)

Накладные расходы на память: каждому объекту требуются метаданные для администрирования. Миллионы мелких объектов фрагментируют рабочую память (ОЗУ).
Промахи кэша ЦП: современные процессоры работают быстрее всего с линейными структурами данных (ориентированный на данные дизайн). ООП разбрасывает данные в памяти, что замедляет работу ЦП.

Это какие-то бейсикопроблемы?
Наследование и правда плохо работает практически всегда и от него почти везде отказались.

vazgen05 ★★★
()

ООП это инкапсуляция, полиморфизм, наследование.

Инкапсуляция может быть полезна.

Полиморфизм и наследование в том виде, в котором они сделаны в ООП - не нужны.

Но в них можно вычленить полезную составляющую. Это интерфейсы.

Т.е. если взять ООП язык, запретить использовать наследование классов, но оставить наследование интерфейсов. Тогда - нормально.

Правда это уже будет не ООП. Но как называть - не знаю.

Также для комфортного программирования желательно дополнять такой ООП функциональной парадигмой.

vbr ★★★★★
()
Последнее исправление: vbr (всего исправлений: 1)

Не хватает тега «я познаю мир»

что скажете?

Да в принципе ничего больше, пожалуй. Отличие данной темы от предыдущих только в url ссылки и в конкретных наименованиях языков, перечисленных как современные в последнем пункте. В остальном по сути всё то же самое, что уже было и в начале нулевых, и в конце, и в начале десятых, и в конце, и в начале двадцатых пару-тройку раз, и вот теперь снова. Ничего нового у меня по этому поводу сказать нет, а старое я ещё в середине нулевых высказал (не с этого аккаунта)…

Пруфов в виде ссылок на предыдущие идентичные (только с другим url, но с почти той же копипастой по нему, как минимум по смыслу (естественно слово в слово я не помню)) темы/посты не будет — я без понятия, как их нормально искать.

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 1)
Ответ на: комментарий от vbr

Т.е. если взять ООП язык, запретить использовать наследование классов, но оставить наследование интерфейсов. Тогда - нормально зачем такое ООП?

Поправил.

anc ★★★★★
()
Ответ на: комментарий от vbr

Да полиморфизм тоже иногда очень удобен. Вот наследование реально вызывает проблемы, пришлось заменить его в итоге.

Вообще все претензии к ООП сводятся к наследованию. В основном.

LightDiver ★★★★★
()
Ответ на: комментарий от LightDiver

Вот наследование реально вызывает проблемы, пришлось заменить его в итоге.

Можно пример? На моей практике с наследованием вроде проблем не встречалось.

anc ★★★★★
()
Ответ на: комментарий от anc

Когда накручиваешь в классе слишком много лишнего, потом последовательное множественное наследование все это сохраняет, а оно тебе нахрен не пилось. И все это копится.

Мне проще композицией объединить в итоге несколько классов. Каждый класс делает что то хорошо и обособленно, имеет интерфейсы взаимодействия, дорабатываетя при желании. А ты их уже через интерфейсы объединяешь и все.

Вот у меня своя реализация баз данных с разными варианатами хранения информации и доступе а ней для разных проектов. Единый класс тут оказался излишним, при наследовании все это тянулось. Разбил на пять раных проектов и подключал их вместо наследования.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от LightDiver

Когда накручиваешь в классе слишком много лишнего, потом последовательное множественное наследование все это сохраняет, а оно тебе нахрен не пилось.

Понял, ошибка проектирования, а не то что я подумал :)
Спасибо!

anc ★★★★★
()
Последнее исправление: anc (всего исправлений: 1)
Ответ на: комментарий от anc

Понял, ошибка проектирования, а не то что я подумал :)

Ну не совсем. Вот представь. У тебя цепочка из нескольких классов, где сохраняется разное из предков. Даже при правильном проектировании у тебя всеравно какая то часть остается «мертвым» кодом. И лучше таких цепочек из десяти потомков лучше не делать, как я понял.

Это как с множественными вложениями ифов в коде.

LightDiver ★★★★★
()
Ответ на: комментарий от anc

В целом верно. Но с композицией сложнее накосячить. У тебя есть классы, которые выполняют свою функцию. Другие классы их используют. Без этого вот всего, где функциональность предка используется в потомке. Это работа равноправных разных сущностей.

LightDiver ★★★★★
()
Ответ на: комментарий от vbr

> ООП это инкапсуляция, полиморфизм, наследование.

Ещё «абстракцию» часто добавляют.

> Полиморфизм . . . не нужны.

Почему?

kaldeon ★★
()

> что скажете?

Про производительность: накладные расходы есть (равно как и у функционального подхода), но для большинства прикладных программ это допустимая цена.

Про наследование: не нужно. Недавно обсуждали здесь [1] (и я ещё вернусь в тред, возможно).

> Go . . . предпочитают композицию

Верно [2].

[1]: Что происходит с популярностью Go? (комментарий)

[2]: https://go.dev/doc/faq#inheritance

kaldeon ★★
()
Последнее исправление: kaldeon (всего исправлений: 2)
Ответ на: комментарий от LightDiver

Ааа.. Если тебе надо интересно - почитай Пратчетта.

Что за дичь…

AZJIO
() автор топика
Ответ на: комментарий от LightDiver

Что за каша в голове у того, кто это писал? Композиция - такой же инструмент ООП, как и наследование

Погуглил «покажи пример наследования в JavaScript», подставляя взамен «наследования» слова полиморфизм, инкапсуляция, композиция. И это весь ООП что-ли? Я считал это просто формой записи языка, в справке это называлось «методы». Как я понимаю сама страница HTML это куча вложенных тегов и стилей и для такой структуры данных методы как раз удачная форма запроса данных объекта.

AZJIO
() автор топика
Последнее исправление: AZJIO (всего исправлений: 1)
Ответ на: комментарий от AZJIO

Весь ООП это создание чертежей (классов), по которым штампуются объекты. Ты описываешь шаблон, потом создаешь по нему экземпляр, загружаешь в него данные и управляешь им. Это основа.

Методы это просто функции класса. Причем их порядок абсолютно не важен, в отличие от обычных функций. Любой метод класса видит другой метод класса независимо от расположения. В этом его и удобство, кстати. Второе удобство - они все проименованы классом.

В итоге ты к любому такому методу можешь обратиться через класс - через объект.

Представь - есть у тебя объект «дом». Теперь ты можешь обращаться к квартирам не просто как отельным сущностям, а как содержимому класса «Дом». Дом.1 - первая квартира. Дом.2 - вторая квартира.

А хочешь второй дом? Тебе не надо его создавать заново. Ты просто создаешь второй экземпляр класса дом и он обладает теми же свойствами, зато независимо от остальных классов.

А еще в классе может храниться информация и к ней тоже можно получить доступ через объект. Есть в доме счетчики воды. И ты можешь обращаться: Дом.1.счетчик - счетчик воды из квартиры один.

Это про удобство оформления и работы с кодом как раз.

А тепер представь, тебе нужен не точно такой класс, а чуть другой дом на основе этого. Ты берешь свой уже давно созданный дом, и наследуешь от него - основа та же, но некотоыре квартиры с другой планировкой. Этот наш новый дом является производной от старого. А проблема тут в том, что унаследовалось еще и подвальное помещение, которое в новом доме в принципе нахрен нам не упилось, ну да ладно - пущай будет.

Ладно, похрен, теперь нам нужен еще один дом. Наследуем от второго, но тут нам уже не нужен чердак, а нужны квартиры и подвал.

И вот так ты тянешь этап за этапом все косяки предков. Потому наследование очень не любят и старатся от него отказаться.

И вот тут нам на помощь приходит композиция. Мы не городим единый класс «дом». Мы делаем разлиные универсальные модули-блоки. Крыша, подвал, квартира. И из этих блоков строим дом. Ели нам надо другой дом, мы объединим их в другой последовательности и все. И во втором доме нам не надо будет тянуть за собой подвал от первого.

А ФП это суровая индивидуальная постройка нового дома по новому проекту из кирпичей. Все вручную, никаких шаблонов. Вот тебе кирпичи, цемент - строй.

В ФП ты можешь гибко все создать, заполнить все пространство по индивидуальному проекта. Но косяк в том, что тебе придется это делать каждый раз. Пока ты будешь строить 5 индивидуальных домов по индивидуальному проекту, я наклепаю по шаблону 5 улиц панелек.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 2)

…что скажете?

Скажу, что тащить сюда этот давно истлевший холивар было глупой затеей.

verdammter_katze
()
Ответ на: комментарий от iZEN

Они вроде как были призваны обеспечить инкапсуляцию.

Хотя давно, когда изучал ООП, не понимал, зачем делать геттеры ии сеттеры, если всё, что они делают, это возвращают и присваивают значение без какого-либо обработки. Это что-то на программистком, наверное.

bbc69
()
Ответ на: комментарий от LightDiver

В ФП ты можешь гибко все создать, заполнить все пространство по индивидуальному проекта. Но косяк в том, что тебе придется это делать каждый раз. Пока ты будешь строить 5 индивидуальных домов по индивидуальному проекту, я наклепаю по шаблону 5 улиц панелек.

То есть я создаю экземпляр структуры двумя словами имя экземпляра и имя структуры, чем ООП-объект будет наклёпан быстрее? Поднималась тема, что современные программы не оптимизированные, и вот этот объект с лишним грузом и есть один из шагов неоптимизации.

Любой метод класса видит другой метод класса независимо от расположения.

Ну просто делаешь их (функции) сверху по коду или декларируешь и можешь их вызов вставлять хоть где и они все доступны.

AZJIO
() автор топика
Ответ на: комментарий от AZJIO

Вот я тебе могу пример как я 2 года не мог понять что такое ООП, потом изобрел его сам на ФП и внезапно у меня произошло прозрение.

Я делал курс по испанскому языку. Представ, у нас есть разные типы тестов. В одном нужно выбрать одну картинку из 4. В другом выбрать две разные. В третьем написать нужное слово итд. Как это сделать?

И я дошел до гениальной идеи - шаблоны!

function loadTest(testTable, testNumber) {
  const test = testTable[testNumber]; // Достали запись

  if (test.type === "reading") {
    // 50 строк кода для загрузки текста с вопросами
    showReadingTest(test);
  } else if (test.type === "listening") {
    // 70 строк кода для загрузки аудио с субтитрами
    showListeningTest(test);
  } else if (test.type === "grammar") {
    // 30 строк кода для загрузки упражнения на грамматику
    showGrammarTest(test);
  } else if (test.type === "speaking") {
    // 60 строк кода для загрузки устного теста с микрофоном
    showSpeakingTest(test);
  }
  // ... и так далее
}

Делаем таблицу с модулями-тестами. Делаем функции для работы с таблицей. Скармливаем функции таблицу с тестами и текущий номер теста. В модуле описано - какой это тип теста. И в зависимости от типа теста подгружается свой код. Это кстати полиморфизм тот самый.

В чем косяк этого подхода? Нет структуры. Если тебе надо надо другой курс, где один тип теста надо чуть изменить, надо будет копировать код, поддеривать отдельную копию.

А с ооп все проще. Делаем единый класс курс. В нем делаемо отдельные методы на каждый тип теста. Все. Создаем экземпляр класса и скармливаем ему нужную таблицу с модулями. Надо другой курс, где есть другой тест? Переопределили метод и все.

Попробуй сам сделать что то подобное на практике и поймешь.

Вот такой же код, как выше, но на ООП:

// 1. Базовый класс (шаблон)
class BaseTest {
  constructor(data) {
    this.data = data;
  }

  load() {
    throw new Error("Метод load() должен быть переопределён в наследнике");
  }
}

// 2. Конкретные классы (каждый со своей логикой)
class ReadingTest extends BaseTest {
  load() {
    // 50 строк кода для загрузки текста с вопросами
    showReadingTest(this.data);
  }
}

class ListeningTest extends BaseTest {
  load() {
    // 70 строк кода для загрузки аудио с субтитрами
    showListeningTest(this.data);
  }
}

class GrammarTest extends BaseTest {
  load() {
    // 30 строк кода для загрузки упражнения на грамматику
    showGrammarTest(this.data);
  }
}

class SpeakingTest extends BaseTest {
  load() {
    // 60 строк кода для загрузки устного теста с микрофоном
    showSpeakingTest(this.data);
  }
}

// 3. Фабрика (единственное место, где выбираем тип)
function createTest(testData) {
  switch (testData.type) {
    case "reading":   return new ReadingTest(testData);
    case "listening": return new ListeningTest(testData);
    case "grammar":   return new GrammarTest(testData);
    case "speaking":  return new SpeakingTest(testData);
    default:          throw new Error(`Неизвестный тип теста: ${testData.type}`);
  }
}

// 4. Главная функция (вместо кучи if-else)
function loadTest(testTable, testNumber) {
  const testData = testTable[testNumber];
  const test = createTest(testData);
  test.load();
}

Делает по сути то же самое, но в структуре.

А вот когда ты выжрешь всю доступную память, тогда потихоньку начнешь приходить к идее композиции. Но для этого ты дожен пройти весь предыдущий путь.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 2)

Егор Бугаенко: «Класс — это вообще ошибка. Не должно быть классов.»

Егор: Понимаю, о чём ты говоришь. Но я не добьюсь результата мягкими действиями. В блоге я в рамках одной статьи вбрасываю, человек читает, немножко меняется. Книжка делает бросок далеко вперёд. Она говорит «Вы здесь, а правильно — вот там, через 20 километров. Как вы туда доберётесь, я не знаю». Как в анекдоте: «Моё дело — стратегия, а с тактикой вы сами решайте». А блог даёт какие-то шаги — тут немножко так, тут так. Книжка забрасывает далеко вперёд и писалась с такой задачей, не на один год — как вброс в будущее. Ну и она должна быть резкой. Тяжело человека сдвинуть. Масса была статей про null и про геттеры-сеттеры. Ты можешь погуглить, не один я это пишу. Почему мои вызывают такой флейм, у меня про геттеры-сеттеры триста комментов за полгода, а у уважаемого Аллена Холуба за десять лет пару комментов? Потому что он говорит мягче. Он говорит «Старайтесь держаться от них подальше, не использовать их». А я говорю «Если ты используешь их, то ты дурак». Естественно, это вызывает реакцию и побуждает к изменениям.

ООП будущего: Барух Садогурский и Егор Бугаенко о том, как мы будем программировать через 20 лет ARG89 1 сен 2016 в 10:27

iZEN ★★★★★
()
Последнее исправление: iZEN (всего исправлений: 1)
Ответ на: комментарий от LightDiver

Что за каша в голове у того, кто это писал?

Ну говоришь что за каша у него, а он спокойно примеры ООП пишет. Мне просто не раз попадались примеры с *this, я нашёл на форуме несколько. Я делаю по необходимости, когда припрёт, когда не понимаешь как решить задачу красивым кодом или просто созрел и увидел применение.

AZJIO
() автор топика
Ответ на: комментарий от AZJIO

Отделять композицию от ООП это всеравно что рассуждать о том, что ООП зло, а нужно только ФП или что ФП зло и нужно только ООП.

Это что то на ультра-религиозном, где понимание сути не важно, а главное - вера.

LightDiver ★★★★★
()
Ответ на: комментарий от LightDiver

Ну хорошо, что ты можешь красиво показать разницу в примерах, а многие выглядят как сектанты, из того что они знают им предоставили объект в программном языке, в котором ты не видишь ничего удивительного, но они ради своего идола будут плевать в тебя и говорить что ты ничего не понимаешь, а там понимать то нечего.

AZJIO
() автор топика
Ответ на: комментарий от AZJIO

В музыке тоже нет ничего сложного по сути. Семь нот всего - даже ребенок изучит легко.

Нюансы возникают, когда надо все это комбинировать и применять в реальности. И тут уже нужно полностью перестроить сознание и узнать много нового, чтобы понять - как же эта срань работает то.

LightDiver ★★★★★
()

Сабж не читал. Многабукаф потомучта. Мнение имею. ООП привинтили к императивщине, чтобы понизить кол-во бойлерплейт лапши, которую везде нужно писать. Это работает, понижает. В функциональщине такой проблемы изначально нет, ибо она декларативна. Но у функциональщины есть другие проблемы, которые решаются с помощью императивщины. Вообще, ЯПы эволюционирут в сторону адскойЪ смеси парадигм, которая в целом повышает декларативность кода, оставляя возможность опускаться до самой низкой императивной мерзости. ИИшечка, кстати, введёт свои поправки в этот эволюционный процесс.

yvv1 ★★
()

Первые три пункта про копейки производительности, на бенчмарках большой разницы не будет, четвертый - ну не создавай огромные ненужные родительские классы, пятый - да можно писать и без ООП, это не доказывает ущербность ООП. Эта критика несерьезная, можно покритиковать и лучше. Вообще что угодно можно покритиковать, и можно писать хорошо и на ООП и без ООП, и на скриптоте и на плюсах, и т.д. и т.п. Где-то легче, где-то тяжелее, где-то одни преимущества, где-то другие.

goingUp ★★★★★
()

Накладные расходы на память: каждому объекту требуются метаданные для администрирования. Миллионы мелких объектов фрагментируют рабочую память (ОЗУ).

Если взять какие-нибудь плюсы, миллион мелких инстансов объектов будет почти полностью состоять из данных, а не метаданных. Не понятно что автор имел в виду, но читать дальше не хочется.

Gary ★★★★★
()

Моё личное про ООП в PHP: Если проект небольшой, то ООП не оправданно. Если проект большой, масштабируемый с изменениями в проекте по ходу работы, если много разработчиков и столько же «идейных вдохновителей», то ООП оправдано.

AnonymUser
()

Зачем ты этот нейрослоп сюда притащил?

firkax ★★★★★
()
Ответ на: комментарий от LightDiver

switch (testData.type) { }

Нафига ты это делаешь? testTable[testNumber] у тебя должен колбек на конструктор нужного класса возвращать, а не testData (который должен каждый класс хранить «speaking» в SpeakingTest и т.д.). Потом просто делаешь callback = testTable[testNumber] и callback().load()

Это называется полиморфизм.

switch в ООП признак плохого или ленивого дизайна. Другой вопрос, что ЯП из 90-х сделаны криво и иногда лень на них городить весь этот ООП через их кривой синтаксис и инструменты. Поэтому, да, проще свитч.

foror ★★★★★
()
Последнее исправление: foror (всего исправлений: 3)
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)