LINUX.ORG.RU

Когда использовать ООП?

 


0

3

Доброго времени суток, господа!

Собственно, сабж. Но сразу оговорюсь, что под ООП в данном случае подразумеваю то самое махровое ООП из пропаганды маркетолухов, Java, C# и т.д.

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

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


Ох и срач же тут начнётся. Объективно правильного ответа на этот вопрос нет.

Обтекаемо будет так: когда работа происходит с объектами, которые можно описать средствами ООП, хотя бы таже тупо такими как классы, а также когда есть какие-то отношения между этими объектами.

Как по мне, игры — это вполне себе та область, где ООП весьма даже применимо. Но это не значит, что использовать ООП обязательно. Многие ещё более легендарные игры (в т.ч. для старых консолей) вообще на ассемблере писали. Что ж теперь, тоже на ассемблере писать что ли из-за этого?

А так, грань, где стоит юзать ООП, а где нет, определяется для конкретного случая индивидуально, причём самим программистом, продумывающим архитектуру, в виду своих предпочтений. Пиши так и эдак, с опытом придёт осознание, где лучше заюзать, а где нет. Иначе никак. Никакой серебряной пули, подходящей и для всех случаев и для всех программистов, нет. С опытом само придёт, и будешь всем доказывать, что именно ты понимаешь, где надо, а где не надо, а остальные дураки либо пихают ООП куда не надо, либо отказываются от ООП там, где с ним было бы проще.

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

Нужно юзать то, что Боссы говорят, но если следовать фильму АССА (фу-ты, этот как его? ну где чувак на лавочке прохожим свою жизнь излагал?), так он говорил, нет - мама его: Босс - Боссу рознь. Есть Босс самопал, а естьe настоящий, например Tim Sweeney. Так Суини юзает ООП на 1000%, что видно по-его результату!

anonymous
()
Ответ на: комментарий от CrX

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

С ООП проще только там, где ничего другого нет. Но таких язычков, конечно, следует избегать.

Nervous ★★★★★
()

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

Классический ООП это патриархальная концепция, не вписывается в современные реалии.

ya-betmen ★★★★★
()

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

А так, используй всё подряд там где это к месту, удобно и разумно и всё.

Как применять инструменты правильно?

Никак, не существует никакого «правильно», правильно так как ты решишь, не бойся принимать решения, не стремись слепо следовать чему-то просто потому что сам боишься сделать что-то не так. Один фиг будет что-то не так, но ты это поймёшь на практике увидев эффекты от решений и применишь иной подход, целиком для проекта или частично для его куска.

Где находится та грань, когда нужно использовать ООП

Для ООП в вакууме нигде она не находится. Тебе удобен подход? У тебя нет необходимости постоянно менять код добавляя фичи и из за этого рефракторить всё что с ним связано после изменений, используй. Видишь проблему связанную с подходом в конкретном случае (буквально модет одном файле) не используй, вот и всё.

что под ООП в данном случае подразумеваю то самое махровое ООП из пропаганды маркетологов

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

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

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

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

Итого, ой всё, исходи из логики, здравого смысла, личного удобства, и анализируй как тот или иной подход в разработке будет влиять на жизненный цикл проекта в перспективе, чем более сложную (пусть и продуманную) модель разработки ты заложишь и которой будешь придерживаться тем большую боль ты гребёшь в случаях когда эта методология и инструменты станут не подходить под условия и выбора у тебя два, либо пойти на компромисы (а они неизбежны) и сохранить подход к разработке и структуру проекта, либо отказаться полностью или частично и сделать что-то просто по другому.

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

Итого, если говорить про игры, то часть проекта у тебя может быть в стиле ООП, чёткая выверена, интерфейсы стабильное API и прочее. А часть чисто процедурная, а часть ещё какая. И норм, все так и делают.

Если проект маленький ну там тысяч 10 строк, то вообще парится не надо используй ваще чё хочешь и всё будет правильным так как переписать часть или даже всё в случае чего не проблема, ну проблема, но не такая когда у тебя кодовая база в 100 тысяч строк где уже и начинаются думы думные, местами жрать кактус, но сохранить консистенстность проекта, без смысла, а чисто в угоду сохранения того подхода который заложен в проекте даже если это во воред всему, логике, здравому смыслу и производительности, или допускать применение совершенно других подходов вплоть у тебя проекта на ООП строгом в рамках некой договорённости, а часть ваще на LISP так как там скорость не нужна, а реализация простая, и интерпретатор лиспа весит целиком меньше чем бы делалось это на плюсах или ещё чём.

Так как же поступать?

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

Дочитал? Во ты псих! Делать тебе больше нечего!

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от rtxtxtrx

Для этого ооп ненужно, можно использовать локальную область видимости интерпетируемой/компирируемой единицы и это из коробки наверное есть в почти любом языке. Что вообще за «модификация из вне»? У тебя будет в любом случае API, а если кому приспичит что-то внутри поменять в обход его и так поменяют.

LINUX-ORG-RU ★★★★★
()

Когда проект коммерческий и когда у бизнеса есть свои заковыристые правила, которых оочень много и когда поток людей - приходят и уходят ну и т.д., т.е. когда время-программисты == деньги и код пишется в рабочем порядке, то лучше ООП, он тут реально спасает. Например, смотри в сторону Domain Driven Design, Clean Architecture и всех этих дядюшек Бобов и Банд четырех… А когда проект для души или стартап или Cuting Edge - там хоть хаскель с чистой философией и функциональщиной без ооп, хоть brainfuck

fpastush
()
Ответ на: комментарий от LINUX-ORG-RU

Нужно. Это защита от дурака + не надо лишние аргументы передавать. Без всего этого будет старый добрый похапе 3:

function do_shit() {
  global $cfg, $db, ...;
  // ...
}

Там рантайм до сих пор засран over 9000 глобальных функций, а еще переменные могут неожиданным образом объявляться после вызова функций.

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

Да не пытаюсь я троллить. Вот есть такой ЯП - скала, который работает под JVM и соотвественно совместим с Java, в котором есть трейты и он внезапно еще и функциональный. Он при этом ООП? Безусловно, это же джава. Просто в 2024м году языки программирования несколько изменились по сравнению с 80ми. И вопрос «использовать ли ООП» он дурацкий.

FishHook
()
Ответ на: комментарий от anonymous

Какой шакал, с каким членом? O_o

На аве у ТС вижу онеме. Мне неприятно видеть онеме, но членов или оскорблений я там не вижу. Разве что оскорблением эстетических чувств.

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

Я выше про ECS писал, угадай что там? Там всё доступно всем и вся, глобально всё, и на этом пишут системы которые так сложны что ООП уже мало и оно даже мешает. Есть ещё и языковые особенности, по началу когда у них не было over 9000 функций всё было оптимально, проект вырос и стало не оптимально. Тоже самое будет в ООП проекте, по началу, интерфейсы и дерево наследований, всё красиво, но спустя время будет лапша из перепленённого месива котрое внутри поменять не сломав что-то снаружи нельзя, а требования изменились так как требуются частые правки и фичи. Любой подход на который ты сел и поехал рано или поздно упрётся в свои ограничения, хотя по началу тот же любой подход будет идеальным, пока правила игры не поменяются или не проявится стена где твой подход уже не удобный, а тупо мешает, но… проект вырос, всё в нём уже так как есть. Либо переписывай либо поддерживай что есть. И это будет всегда и у всех без исключений. Кто упрётся в жуткий рефракторинг пожирающий мегатонны времени, кто упрётся в производительность, кто упрётся в расширяемость, кто в лапшакод, кто в over9000 никак не организованных функций которые просто нельзя взять и убрать и так далее. Это просто так есть, ни хорошо, ни плохо. Просто те у кого всё хорошо пока не упёрлись в свой личный потолок.

А по поводу изначальных и на данный момент неправильных архитектурных решений, ну… Не угадали что будет спустя хренлион лет, и ты не угадаешь, выбери любое направление, выбери любой подход, гри смиарити какой я классный, но пройдёт время и ты сядешь в туже лужу только уже свою так как неизбежно упрёшься в ограничения своего подхода так как подход к разработке, ООП и прочее это и есть некий свод правил выраженных через ограничения и когда то самое что вне рамок твоих ограничений должно стать твоей фичей ты сел в лужу так как твои правила их исключают, подход у тебя такой, весь код у тебя на это построен, вот и всё. Так что, может и нужно, я не спорю, но не везде и не всегда и лишь в данный момент.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от FishHook

«устарелый» плюсовой «концепт», в силу своей общности, легко кроет «современное ооп», которое просто является его частным случаем.

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

Используй декларативщину в простых как палка сценариях и натуральные коллбеки вместо синтаксического сахара и тебя будут любить, преймущественно сзади

DumLemming ★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Где тут альтернатива ООП?

// Компоненты
class Position {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
}

class Velocity {
    constructor(vx, vy) {
        this.vx = vx;
        this.vy = vy;
    }
}

class Renderable {
    constructor(sprite) {
        this.sprite = sprite;
    }
}

// Сущности
const createEntity = (() => {
    let entityId = 0;
    return () => entityId++;
})();

// Менеджер сущностей
class EntityManager {
    constructor() {
        this.entities = new Map();
    }

    addComponent(entity, component) {
        if (!this.entities.has(entity)) {
            this.entities.set(entity, []);
        }
        this.entities.get(entity).push(component);
    }

    getComponents(entity) {
        return this.entities.get(entity) || [];
    }
}

// Системы
class MovementSystem {
    update(entityManager) {
        for (let [entity, components] of entityManager.entities) {
            let position = components.find(c => c instanceof Position);
            let velocity = components.find(c => c instanceof Velocity);

            if (position && velocity) {
                position.x += velocity.vx;
                position.y += velocity.vy;
            }
        }
    }
}

class RenderSystem {
    render(entityManager, context) {
        for (let [entity, components] of entityManager.entities) {
            let position = components.find(c => c instanceof Position);
            let renderable = components.find(c => c instanceof Renderable);

            if (position && renderable) {
                context.drawImage(renderable.sprite, position.x, position.y);
            }
        }
    }
}

// Использование ECS
const entityManager = new EntityManager();

const entity1 = createEntity();
const entity2 = createEntity();

entityManager.addComponent(entity1, new Position(100, 100));
entityManager.addComponent(entity1, new Velocity(1, 1));
entityManager.addComponent(entity1, new Renderable(new Image()));

entityManager.addComponent(entity2, new Position(200, 200));
entityManager.addComponent(entity2, new Velocity(-1, -1));
entityManager.addComponent(entity2, new Renderable(new Image()));

const movementSystem = new MovementSystem();
const renderSystem = new RenderSystem();

function gameLoop(context) {
    movementSystem.update(entityManager);
    renderSystem.render(entityManager, context);
}

function startGame(canvas) {
    const context = canvas.getContext('2d');
    setInterval(() => gameLoop(context), 16); // ~60 FPS
}

const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
startGame(canvas);
rtxtxtrx ★★
()
Последнее исправление: rtxtxtrx (всего исправлений: 1)
Ответ на: комментарий от rtxtxtrx

Это не альтернатива ООП, это просто не ООП пусть и с примесями. Зачем чему-то быть альтернативой ООП? ECS это ECS, ООП это ООП, Линукс это линукс, Виндовс это Винда. Они сами по себе, а не альтертативы. Конечно все пары/тройки/четвёрки и так далее имеют схожесть, имеют общие черты и применение у них одно даже, но CLI интерфейс не альтернатива GUI интерфейсу, вернее альтернатива, но только в том плане что это альтернативный вариант, а не альтернатива в смысле там всё также как было. Вещи можно делать просто по разному, вот и всё. Я не говорю что ООП по умолчанию ненужно, или айда все на ECS или ещё какую хрень. Нет, я просто против мании во всём видеть ООП и всё сводить к ООП, ого в ООП есть методы, а методы это функции значит всё у чего есть функции (процедуры!) это жалкое недоООП! И так ведь реально говорят. Что нравится, удобно и решает задачу то и используй, вот и всё. Ладно, я ещё сам себя поругаю, нравится всё называть ООП штырит кого от этого, да и похер пусть, но это рождает кучи недопонимания и глупых холиваров когда все говорят про одно, а подразумевают разное :D

Где тут альтернатива ООП?

Тут то что в ООП реализовать нельзя by desing. А именно возможность на лету менять логику работу программы, так как связность кода нулевая (ну почти, в реальности нет), вопросы реализации кишков ECS стоят особняком. Но суть в том что если уж смотреть на разницу то она проявится тогда когда ты упрёшься в то что для добавления фичи тебе нужно рефракорить код и всё что от него зависит, а тут ты можешь просто выключить/включить систему на лету и всё. У тебя дом и лошадь, дом стоит, лошадь умеет срать, сделай на ООП чтобы дом начал срать, в классическом ООП тебе нужно менять код дома, в ECS ты просто накинешь на дом компонент для срать в рантайме и нужная система которая уже есть сделает обосравшийся дом и это без измененения кодовой базы проекта вообще, если тебе такое не нужно то тебе не нужен ECS, если тебе такое нужно ты как дом обосрёшься с ООП =), но если ты с ECS будешь ну слишком гибкую систему делать то и тут обосрёшься ибо вариативность будет такой что ты в ней просто ориентироваться не сможешь. Всё имеет разумные границы, и под разумностью тут понимается то, какую сложность проекта разраб может держать у себя в голове, от того и разумность тут разная. Всё сводится к банальщине про которую уже говорил, тупо удобство, и некие побочки с которыми можно мирится и учитывать, но всё имеет предел.

Ещё раз, что удобно, что решает проблему то и используй, нет смысла говорить, а как XXX альтернативит YYY, они либо решают поставленные задачи, либо нет, уровень кактусожевания каждый для себя определяет сам.

А так, всё можно свести к процедурному программированию и оно решает абсолютно любые задачи, пусть я сейчас могу делать финты ушами на Lua такие что Lisp обзавидуется, но я рад что я когда то начал с сишки вижу что всё можно свести к процедурам, пусть порой без сахара, ну и ладно.

Декомпозируй подход, и любой подход будет просто кучкой баральностей в рамках неких искусственных правил, которые несомненно важны так как поддерживают целостность и ясность, но рано или поздно из надёжного фундамента превращаются в проблему, но это не плохо, вся суть разработки это решение проблем, в том числе и внутренних, обнимаемся и радуемся что у нас есть возможность чудовищно гибкой вариативности их решения, хотя всё можно свести повторюсь к процедурщине и она будет надёжна, удобна, поддерживаемая и всё такое прочее. ООП, ECS и иже сними это просто оптимизации бойлеркода и всё. Порой, его и не нужно оптимизировать, а порой ваще без разницы, а порой это даже плохо так как всё приходит к автогенерации результатирующего кода который вообще понять никто не может, со всеми эффектами скорость сборки, сложность компиляторов/интерпретаторов, потребление терабайт памяти для сборки на ровном месте и прочее. Лучшим решением в конкретной ситуации будет то что балансирует между, удобством, приемлемым количеством побочных эффектов, как прямых так и косвенных и собсна решение проблемы/задачи, насколько хорошо ложится подход на это.

Цель сего описания такова. Мне пофигу, Бю :)

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

Причём частично или полностью эта (я продолжу утверждать) просто солянка реализуемая на чём угодно, если так хочется.

метатаблица, метатаблица, в глазах двоится

ann_eesti
()

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

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

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

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

Код и данные разделяют, потому что такова фундаментальная природа и нашего моделирования мира, и требований производительности. Хочешь делать в 1000 раз быстрее, значит у тебя будут данные тут, а код для них в другом месте и никаких vtable

max_lapshin ★★★★★
()

ООП это не для программистов, это для философов. Объект противопоставляется субъекту, он по определению то, что субъекту «дано». Субъект - это тот, кто мыслит (в случае компьютеров - обрабатывает объекты).

А как там это всё программисты будут использовать - кого это волнует?

Shushundr ★★★★
()

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

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

Потому что только наследование более-менее признано вредным. Полиморфизм и инкапсуляция есть не только в ООП. Ещё классическое ООП это медленно, так как требует dynamic dispatch в рантайме, его сейчас заменяют дженериками и шаблонами.

neumond
()

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

Потому что ООП сильно переоценено и в реальных проектах редко можно встретить какие-то сложные иерархии объектов.

urxvt ★★★★★
()

Давай сначала определимся, что такое опп.

Object can do exactly three things

  1. Hold state (references to other objects).
  2. Receive a message from itself or another object.
  3. In the course of processing a message, send messages to itself or another object.
beastie ★★★★★
()