Композиция vs. Наследование

Статус
В этой теме нельзя размещать новые ответы.

Bermuda

Новичок
Композиция vs. Наследование

Вычитал в книге, что композиция выгоднее наследования. Почему разработчики злоупотребляют наследованием? Лень? Недостаток знаний, опыта? Или все же наследование удобнее композиции?
 

StUV

Rotaredom
Почему разработчики злоупотребляют наследованием?
главное слово здесь - "зло" =)

т.е. композицию и наследование не надо пихать параллельно внутреннему датчику сл. чисел - а только там где надо и как надо
 

Bermuda

Новичок
Rammstein
Я действительно думаю, что фундаментальным трудам верить стоит.
 

Rammstein

PHPClub::News
Bermuda
А я думаю, что ты вырвал два слова из книги страниц эдак в *00, ибо в разных случаях нужно использовать разные методы/патены

-~{}~ 24.01.07 17:50:

И в "фундаментальном труде" не могли такого сказать однозначно.
 

Bermuda

Новичок
Автор оригинала: Rammstein
Bermuda
А я думаю, что ты вырвал два слова из книги страниц эдак в *00, ибо в разных случаях нужно использовать разные методы/патены
Абсолютно верно, я читаю книгу. По ходу книги возникают вопросы. В параграфе "Механизмы повторного использования" объясняются плюсы/минусы наследования и композиции. Сам чаще использую наследование, авторы же говорят
Это подводит нас ко второму правилу объектно-ориентированного проектирования: предпочитайте композицию наследованию класса.
и там же
Тем не менее, наш опыт показывает, что проектировщики злоупотребляют наследованием. Нередко дизайн мог бы стать лучше и проще, если бы автор больше полагался на композицию объектов.
Я осознаю, что это рекомендация, а не догма и каждая задача требует своего инструмента.

И в "фундаментальном труде" не могли такого сказать однозначно.
Точно, не могли.
Design Patterns
Erich Gamma, Ralph Johnson, Richard Helm, John Vlissides
 

voituk

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

Rammstein

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

Т.е. фактически это получилось из понимания того, что как данные - это единое целое, а вот логика должна разделяться физически по разным классам (как бы объяснить... удобно по многим причинам, в т.ч., возможность замены Account на другой класс, на что скорее всего намекает автор).

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

syfisher

TDD infected!!
Bermuda Почитай книгу Р. Мартина "Быстрая разработка программ" (Agile software development). Там объяснены принципы Open-Closed, Single Responsibity и т.д. Это даст тебе ответы на твои вопросы. Заодно очень серьезно подкует в плане ООП.
 

Макс

Старожил PHPClub
> Почему разработчики злоупотребляют наследованием?

ИМХО

Часто многие авторы (а также преподаватели), рассказывая об ООП начинают с объяснения 3-х основных концепций : инкапсуляции, полиморфизма и наследования.

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

whirlwind

TDD infected, paranoid
Тогда я ввожу объект Account, который будет кошельком, аки счётом, но т.к. он не может существовать без чела - композиция тут идеальный вариант.
Если оно не может существовать вне сущности, то композиция здесь не нужна. Но все дело в том, что многие сущности, которые некогда были выделены из некоторой другой, таки могут существовать (ака быть инкапсулированы) в других классах. В частности, данный случай. Что мешает передать кошелек некоторой организации, или выбросить его в трэш? Как дополнительный плюс такого подхода, если мы используем класс кошелька, мы можем без проблем менять его внутреннее устройство. И это никак не отобразится на механизме передачи кошелька от чела к организации или на процессе выбрасывания.

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

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

Rammstein

PHPClub::News
whirlwind
Composition happens when one class instantiates another, the second class “dieing” when the first class dies.

In other words the first class controls the whole of the second class.
ИМХО, это именно тот случай. Кошелёк НИКОГДА не нужно будет отделён/передан от юзверя и их раздельное существование бессмысленно.
 

Alexandre

PHPПенсионер
[offtop]Загадки от архитектуры
у меня был проект, где базовым классом служил класс логирования, а все классы являлись его наследниками.

Типовая архитектура WEB приложения ()

- базовый класс типичная страница
включает классы (реализует интерфейсы)
- подключение базовых классов работы с БД
- подключение базовых классов темплейтного движка
- подключение базовых классов инициализации
- классы HTTP фильтры и базовой обработки форм (хотя это можно пихнуть в модель)

- класс конкретная страница, наследник базового класса страница.
реализует:
- класс логики ротработки страницы (вызывает классы работы с БД )
- класс представления данных (вызывает классы темплейтного движка )
 

denver

?>Скриптер
Alexandre
[imho]Человек пишущий "+1" или "согласен" просто для того чтобы написать что он согласен предрасположен к стадным инстинктам[/imho]
Дык эта.. к чему этот бесмысленный последний пост озаглавленный "Загадки от архитектуры"? Да и вообще, тема "универсального веб-объекта" не раскрыта.
 

apt-get_mebeer

Новичок
Как бодрость духа?
Начал изучать ООП более детально. Возник вопрос насчет композиции, набросал небольшой код:

PHP:
<?php
/*
 * Класс для работы с точками доступа клиента (HotSpot)
 */
class Points {

    public function  __construct() {
        //pass
    }

    /**
     * Метод возвращает количество активных точек для указанного клиента
     * @param <type> $clientID
     * @return <array()>
     */
    public function getCountActivePointsByClientID($clientID) {
        $sql = "
            select count(id) from points where client_id = {$clientID} and is_deleted = false
        ";
        return $this->db->executeOne($sql);
    }

}

/*
 * Класс для работы с банковскими реквзитами клиента
 */
class ClientAccountingDetails {

    public function  __construct() {
        //pass
    }

    /**
     * Метод проверяет, удален ли ИНН клиента 
     * @param <int> $clientID
     * @return <int> 
     */
    public function getActiveTaxIdentificationNumberByclientID($clientID) {
        // тут проверка удален ли ИНН клиента из системы, если удален то такого клиента нельзя удалять с БД пока не удалить ИНН
        $sql = "
            ........
        ";
        $x = $this->db->execute($sql);

        if($x == 1) { // не удален
            return 1;
        } else { // удален
            return 0;
        }
    }

}


class Clients {

    private $points;
    private $clientAccountingDetails;

    private $_clientID;

    public function  __construct($clientID) {

        $this->_clientID = $clientID;

        // Создвем наши кубики (коллекцию)
        $this->points                  = new Points();
        $this->clientAccountingDetails = new ClientAccountingDetails();
    }

    public function dropClient() {

        // Если у клиента все еще еcть активные точки доступа то не удаляем
        $countPoints      = $this->points->getCountActivePointsByClientID($this->_clientID);
        $activeTaxAccount = $this->clientAccountingDetails->getActiveTaxIdentificationNumberByclientID($this->_clientID);

        if ( $countPoints > 0  and $activeTaxAccount == 1) {
            // ... ничего не делаем и информируем пользователя о том что клиента нельзя удалять и прекращаем сценарий
        } else {
            // ... тут уже начинаетс удаление клиента и конец
        }
    }

}


/*
 * Подтип класса Clients (Обычный клиент)
 */
class SampleClient extends Clients {

    public function  __construct($clientID) {
        parent::__construct($clientID);
    }


}

/*
 * Подтип класса Clients (V.I.P клиент)
 */
class VipClient extends Clients {

    public function  __construct($clientID) {
        parent::__construct($clientID);
    }

}


/*
 * Ну и наконец само использование этого кода
 */
...
$obj = new SampleClient($clientID);
$obj->dropClient();
...

//и тоже самое
...
$obj1 = new VipClient($clientID);
$obj->dropClient();
...
Точка доступа не может существовать без клиента.
Банковские рекивизиты клиента, аналогично.
Я правильно понял композицию?
 

fixxxer

К.О.
Партнер клуба
А постарее треда не мог найти?

Чета не понял при чем тут композиция. Такими темпами любой набор взаимодействующих классов (а кому нужны не взаимодействующие?) можно назвать композицией.
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху