Ответы пользователя по тегу ООП
  • Decorator реализующий интерфейс, а не конкретный класс, возможно ли?

    @Mercury13
    Программист на «си с крестами» и не только
    Так, проблему понял (извините, больной слегка, соображаю плохо).

    Перед нами явно ломаная абстракция: нам надо глубоко внедряться в объект. Тут одно из двух.
    1) Бить объект на два, Repository с create() и update(), и DataStorage с save(). Тогда прослойкой между этими объектами можно пристроить валидатор.
    2) Налаживать точку для подключения внешнего валидатора в save().

    P.S. Декоратор и должен реализовать интерфейс, однако набор возможностей, которые он может делать с этим интерфейсом, невелик.
    Ответ написан
    5 комментариев
  • Как в с++ добавить переменную в обьект уже определённого класса?

    @Mercury13
    Программист на «си с крестами» и не только
    Способ 1. Наследование.
    class Entity
    {
    public:
      virtual ~Entity() {}    // для корректной работы динамических структур данных 
                              // наподобие менеджеров уровней; в нашем примере не нужно;
                              // в реальной игре потребуется
    }
    
    class Player : public Entity
    {
    public:
       bool isDead;
    }
    
    int main()
    {
       Player player;
       player.isDead = true;
       return 0;
    }


    Если кто-то отдаёт Entity, окторый гарантированно Player — то
    Player& somePlayer = dynamic_cast<Player&>(someEntity);


    Способ 2. Композиция
    class Player
    {
    public:
       Entity entity;
       bool isDead;
    }


    Способ 3. Словарь. Это уже на случай, когда чужой код настолько монолитный, что ничем его не прошибёшь.
    struct PlayerInfo
    {
        bool isDead;
    }
    
    std::map<const Entity*, PlayerInfo> playerInfo;


    Если чужой код монолитный, а объекты ещё и перемещаются по памяти — тогда выяснить, что будет «значением» объекта (например, какой-нибудь идентификатор).

    typedef std::string PlayerId;
    std::map<PlayerId, PlayerInfo> playerInfo;


    Если и код монолитный, и «имя» или «значение» объекту никак не придумаешь — тогда никак.
    Ответ написан
    9 комментариев
  • Может ли юнит-тест метода класса зависеть также от других методов?

    @Mercury13
    Программист на «си с крестами» и не только
    Да, может. Всё, что я здесь пишу, — моё ИМХО, обусловленное вечной нехваткой времени и ошибками в базовых функциях (высокоуровневый код тестировать крайне сложно и я не в курсе, есть ли стандартные методы автоматизации тестирования).

    Излишне сложный код тестовых функций также приходится тестировать — поэтому нет ничего зазорного в том, чтобы использовать функции, проверенные другими тестами. Собственные низкоуровневые функции стоит использовать, если они либо проще, либо заводят объект в какое-то контролируемое состояние, которого сложно достичь общедоступным интерфейсом. Таким образом, код теста должен быть примерно такой.
    1. Собрать нужный нам список.
    2. Проверить, что список в нужном нам состоянии.
    3. Удалить один элемент.
    4. Проверить, что новое состояние правильное.

    В пунктах 2 и 4 проверок может быть много — например, в пункте 2 «список корректно связан, в нём 3 элемента и два последних Б, В», в пункте 4 — «список корректно связан, в нём 2 элемента и последний Б». Главное, чтобы а) проверялась одна концепция — например, «работает удаление с конца»; и б) все концепции, которые нужны для корректной работы теста — например, «конструируется пустой список», «добавить в пустой» и «добавить в конец» — тоже надо проверить.

    С зависимостью тестов друг от друга немного неоднозначно. Тесты не должны физически вмешиваться друг в друга: при отладке нужно запускать какое-то подмножество или даже один отказавший тест. Или изменилась внутренняя структура объекта и часть тестов вообще убираем, так как пропадает тестируемая концепция. А логическая — «если добавление не работает, этот тест бессмысленный» — да никаких проблем!
    Ответ написан
    2 комментария
  • PHP. ООП. Сухие примеры с книг, а применять на проектах не получается, как быть?

    @Mercury13
    Программист на «си с крестами» и не только
    В ≈90% веб-работ ООП либо вообще не нужно, либо используется какой-то чужой объект как чёрный ящик. В чём дело? А в том, что сессия PHP недолговечна. Отдал пользователю страничку — и кирдык. А всё, что нужно припрятать до новой встречи, рассовываешь по кукам, сессиям и БД.

    Я бы посоветовал: а) экспериментировать с чем угодно другим, кроме веба; б) если есть возможность, писать в более-менее объектном стиле на JavaScript.

    P.S. И вторая причина — почти всё, что нужно вебисту, уже кем-то написано, остаётся только собрать всё это в единый сайт. И третий совет: где в серверном вебе легко найти применение ООП, так это в поддержке сложных форматов (вики-разметка, например) и сложных протоколов.
    Ответ написан
    2 комментария
  • Что такое нарушения принципов ООП?

    @Mercury13
    Программист на «си с крестами» и не только
    Нарушение инкапсуляции. Наружу (т.е. public) торчат какие-то данные, которые можно изменить, и объект уходит в противоречивое состояние.

    Инверсия абстракции. Простые вещи, которые, вероятно, понадобятся потомкам, недоступны даже через protected.

    Нарушение принципа Лисков (ломаная абстракция). Для отца вы сделали некое предположение, которое неверно для сыновей. Классический пример — прямоугольник и квадрат — предполагается, что отец может произвольно масштабироваться, что неверно для сына.

    Класс вместо интерфейса. Если можно, родителя делайте классом без данных с двумя видами функций: public virtual = 0, и protected/public не-virtual (т.н. интерфейс с утилитами). Наследоваться от нескольких классов с данными очень некузяво (а во многих языках вообще невозможно).

    Всемогущий родитель. Слишком много функциональности придумали родительскому классу.

    В общем, покажите интерфейсы (protected/public, без точных реализаций) ваших классов, и погоняем, что там неверного.
    Ответ написан
    Комментировать
  • Как правильно написать MutexLocker?

    @Mercury13
    Программист на «си с крестами» и не только
    pthread_mutex_locker locker(&mutex);

    Назови его как-нибудь, и всё будет окей.
    Ответ написан
    Комментировать
  • Зачем нужен ООП?

    @Mercury13
    Программист на «си с крестами» и не только
    Я хотел спросить: вы что, студент? Потом посмотрел: нет, вебист. Вебистам действительно ООП нужно крайне редко; если не связывался с хитрой поддержкой сложных протоколов или со сложными моделями данных — в памяти, не в БД — можно писать без ООП и быть успешным вебистом.

    Я и сам долгое время не понимал, на что нужны эти объекты. Главный вопрос: ДЛЯ ЧЕГО?

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

    Предлагаю начать с простого.

    1. Объектный синтаксис. Было…
    iDog : integer;
    iDog := SpawnMonster(world, mtDog, x, y);
    ChargeAtPlayer(iDog);


    Стало…
    dog : TMonster;
    dog := world.SpawnMonster(mtDog, x, y);
    dog.ChargeAtPlayer;


    Уже стало красивее. Да и номер собаки можно случайно передать, например, вместо номера оружия; с типом TMonster такой фокус не пройдёт.

    2. Инкапсуляция.
    Это мы уже думаем над тем, чтобы вызовы функций не могли привести объект в «ненадлежащее» состояние, а всё, что может объект подпортить,— засунуто в private.

    3. Абстракция и наследование. Это уже «сложный пилотаж». Не высший — это неотъемлемая часть навыков хорошего программиста, да и для 80% задач это не нужно, зато в остальных 20-и очень улучшает жизнь. Самый простой пример. В какой-нибудь 2D-игре есть некий TGameObject, у которого виртуальные функции Live и Render. Первая прокручивает такт «жизни» объекта, вторая рисует его на экране. TGameObject можно разбить на TPlayer, TProjectile, TEnemy и TBonus, и т.д.

    Ах да. Для ООП не нужен объектно-ориентированный язык и объектный синтаксис, нужно объектно-ориентированное мышление. Например, Doom был написан на Си, но в очень-очень объектном стиле.
    Ответ написан
    Комментировать
  • Как работать Excel-документами в Delphi?

    @Mercury13
    Программист на «си с крестами» и не только
    Есть два варианта, автоматизация OLE и прямая поддержка XLS-файлов.

    Я сумасшедший и по спецификациям Micro$oft написал второе (всё-таки в коммерческой программе, от которой, впрочем, не требуются никакие оформительские изыски, так лучше).

    Для разовой утилиты лучше первое. Ещё можно работать через CSV.
    Ответ написан
    2 комментария