За последние 24 часа нас посетили 23742 программиста и 1549 роботов. Сейчас ищут 1033 программиста ...

Наследование классов в ООП. Вопрос в подходе.

Тема в разделе "Прочие вопросы по PHP", создана пользователем Kotoffsky, 3 мар 2011.

  1. Kotoffsky

    Kotoffsky Активный пользователь

    С нами с:
    3 мар 2011
    Сообщения:
    4
    Симпатии:
    0
    Переписываю заново довольно крупный проект, поэтому встал вопрос о том как лучше использовать классы. Напишу сразу на живом примере, так будет понятнее, что именно я бы хотел у вас узнать.

    У меня есть классы Mysql (с функциями базы данных) и System (с функциями которые используются на любой странице сайта).

    Для каждого из крупных разделов сайта я создаю класс, например Новости , Вопросы, Обновления.

    Наследование получается таким:
    Mysql -> System -> Новости
    Mysql -> System -> Вопросы
    Mysql -> System -> Обновления

    Но тут у меня появился класс Комментарии, функциями которого я хочу, чтобы умели пользоваться Новости.

    Здесь я столкнулся с дилеммой. Можно сделать так:
    Mysql -> System -> Комментарии -> Новости

    А можно так:
    Mysql -> Комментарии
    Mysql -> System -> Новости (с объявлением внутри объекта $comments = new Комметарии и его использованием)

    В первом варианте меня смущает, что при появлении еще одного класса для новостей вроде Комметариев (например Голосование) получится так:
    Mysql -> System -> Комментарии -> Голосование -> Новости.
    А это значит, что голосование всегда будет наследовать комментарии, а не должно.

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

    Быть может где-то я ошибаюсь в своих рассуждениях или не рассматриваю какой-нибудь третий более оптимальный вариант. Как бы в такой ситуации поступили бы вы?
     
  2. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    не нужно никакого наследования,
    почитайте про ServiceLocator, Dependency Injection и MVC
     
  3. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    У вас каждый класс свое подключение создает? Если так, то это неверный подход. Коннект один должен быть, да и вообще все запросы должны через один класс идти.

    Обычно делается Синглтон для таких вещей. А остальные классы уже пользуются его методами
     
  4. Kotoffsky

    Kotoffsky Активный пользователь

    С нами с:
    3 мар 2011
    Сообщения:
    4
    Симпатии:
    0
    С MVC знаком, а про ServiceLocator и Dependency Injection почитал немного, выглядит заманчиво, но довольно расплывчатую информацию пока нашел. Не совсем пока понял как их воспринимать, как готовые паттерны, которые нужно взять и пользоваться или как подход на основе которого надо написать свой код.
    Методы работы с базой данных описаны только в классе Mysql, а другие классы их наследуют и пользуются. Коннект к базе происходит в конструкторе класса MySQL. В конструкторе других классов вызывается конструктор родителя.

    Например, объект Новости при создании вызывает конструктор объекта System, а конструктор System вызывает конструктор MySQL, который создает соединение. Чую, что как-то мутно получается, поэтому и написал сюда.

    Правильно ли я понимаю применение Singleton? Каждый из классов обращается к Singleton, который если объект класса Mysql не существует - создаст его, а если существует, то будет работать через него? То есть в моем конкретном примере он будет вызываться Новостями и Комментариями. В случае если используются только Комментарии, то они создадут MySQL объект через singleton. А если же в составе новостей, то до этого его создадут Новости, а Комментарии будут уже им пользоваться?

    Прошу прощения, если в моей голове картина происходящего вдруг отклоняется от действительности)
     
  5. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Kotoffsky
    статики рулят в таком деле. даже экземпляр класса создавать не нужно =) и доступны везде без глобальности.
     
  6. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    Этот конструктор родителя как раз и будет создавать новое подключение в каждом классе, а это не есть гуд.

    Да, примерно так и есть. При первом обращении создается синглтон(в нем соединение с базой). При повторном обращении проверяется - если объект уже создан (подключение к базе есть), то возвращается этот объект. Если нет - создается.

    http://ru.wikipedia.org/wiki/%D0%A1%D0% ... 0%BE%D0%BD

    Можно и статику использовать, как igordata сказал. Это тоже широко применимо. Само подключение сделать функцией, а уже запросы - статическими методами класса MySql
     
  7. titch

    titch Активный пользователь

    С нами с:
    18 дек 2010
    Сообщения:
    847
    Симпатии:
    0
    В общем случае - да. Но я видел систему, где доступ контролировался мускулом (на каждый модуль свой mysql-акк). Работало шустро и уровень защиты высокий. Решение мне не очень нравится, но рациональное зерно в этом есть.
     
  8. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    titch Профилировал работу с базой на одном из своих проектов. Большинство запросов - менее 0,01 сек (без Джоинов, индексы стоят). Тогда как соединение с базой - 0,2 может занять.

    обычно на одну страницу сколько запросов приходится? 10-12 как максимум?
    Имхо для 10 запросов 4 подключения делать - переборчик))))
     
  9. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    titch
    зависит от задачи. На новостном сайте наверное нет смысла в такой крутой штуке. Но сам всегда задумываюсь о реализации на нескольких аккаунтах.
     
  10. Kotoffsky

    Kotoffsky Активный пользователь

    С нами с:
    3 мар 2011
    Сообщения:
    4
    Симпатии:
    0
    Всем спасибо за ответы.

    Singleton и вправду хорошо вписывается в то что уже есть. Так что пока буду реализовывать так:
    Класс Singleton будет содержать статичную функцию getInstance() (как на википедии).
    Класс Mysql extends Singleton и в конструкторе содержит подключение.
    В свою очередь Mysql уже никто наследовать не будет, а будут вызывать MySQL::getInstance().

    Остальные классы выходят так:
    System -> Новости (с объектом $comments = new Комментарии)
    System -> Вопросы
    System -> Обновления

    Другие варианты реализации буду тоже держать в голове на случай непредвиденных обстоятельств)
     
  11. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Kotoffsky
    мускул вполне можно сделать статиком. статик не забывает. =) просто после объявления класса сразу можно написать подключение и забыть о том что он статик. И все будет круто.
     
  12. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    Kotoffsky

    Как вариант - внутри класса Mysql содержится объект Singleton. В конструкторе он вызывается через getInstance().
    Остальные классы наследуются от Mysql

    В итоге - внутри всех конструкторов будет вызываться один и тот же объект Singleton, зато функции Mysql будут доступны через $this
     
  13. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    DB::query(); проще =) глобальнее, пляшет и поет.
     
  14. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Kotoffsky
    Скорее всего нужно не наследование, а включение. Возможно статика
    igordata
    Пляшет и поет, пока не понадобится второе подключение.
     
  15. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Volt(220)
    если количество подключений заранее известны, то все просто.

    Если нет, то все равно можно юзать один статик класс, переключая отдельным методом, или выбирая подключение сразу в методе запроса, фигли =)
     
  16. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    igordata
    Да без проблем.
    Но подход с наличием двух(и более) объектов мне кажется более понятным и простым чем всякие переключения...

    У меня изначально была задача работать с двумя базами в итоге получилась фабрика:
    Код (Text):
    1. SQLDBFactory::getDB();
    вернет подключение по конфигу из настроек (если его еще нет то создаст)
    Код (Text):
    1. SQLDBFactory::getDB($config);
    создаст новое подключение с параметрами $config.
    Код (Text):
    1. SQLDBFactory::getAlterDB();
    Вернет подключение ко второй базе (если его еще нет то создаст).