Ответы пользователя по тегу ООП
  • Использовать ли наследование?

    @D3lphi
    Наследование применяется, если можно сказать, что что-то является чем-то. Например, разработчик является работником; компьютер является устройством и тд.

    Задайте себе вопрос: "Является ли девайс сокетом?" и сразу все поймете.
    Ответ написан
    Комментировать
  • Есть ли какие-либо недостатки у статических методов?

    @D3lphi
    Значит так, берем толстую тетрадь, ручку и пишем фразу "Статические методы не имеют отношения к ООП" до тех пор, пока не запомним это на всю жизнь.
    Суть объектно ориентированного программирование, как понятно из названия, заключается в том, что должен существовать объект. Статика существует не в контексте объекта, а в контексте класса! Из этого вытекает то, что на протяжении всего жизненного цикла вашего кода будет существовать лишь одно глобальное состояние статических членов класса.

    Использовать статику нужно в случае, если то, что вы ей описываете принадлежит всей группе объектов, а не одному. Например, у класса Human может быть статический метод numberOfLegs(), который возвращает количество ног у людей. Количество ног - это общее свойство для всех людей (Речь идет о здоровых людях). В данном случае можно было использовать константу класса, но это не так важно, ведь, по сути, константа - это тоже статический контекст. А вот имя - это уже свойство каждого отдельного человека. И очень важно чтобы статические методы не изменяли состояние системы в целом, не содержали побочных эффектов.
    В статические методы можно выносить какую либо служебную логику. Например, метод перевода числа из арабской в римскую запись следует сделать статическим.

    Есть ли у статического варианта какие-то подводные камни

    Большое количество. При чем, не таких уж и подводных. Из-за того, что статика глобальна, она плохо поддается тестированию, ее нельзя замокать. Глобальное состояние плохо поддается отладке. Отсутствует возможность подменить реализацию, так как это позволяют сделать объекты.
    Ответ написан
    4 комментария
  • Почему ошибка при отсутствии необязательного модификатора доступа в классе PHP?

    @D3lphi

    Методы класса должны быть определены через модификаторы public, private, или protected. Методы, где определение модификатора отсутствует, определяются как public.

    Внимание, вопрос: ниже вы объявляете метод или, все-таки, свойство?
    class A{
       public $attribute = 5;
    }
    Ответ написан
    8 комментариев
  • Что значит глобально доступный объект приложения?

    @D3lphi
    Глобальный объект доступен из любой точки приложения. Примером такого объекта является экземпляр класса, с использованием (анти)паттерна singleton. Любой разработчик из любой точки кода может получить этот объект как-то так:
    object = Example.getInstance();
    Ответ написан
    1 комментарий
  • Как разобраться в ООП PHP библиотеке?

    @D3lphi
    С чего начать разбирательство? В каком файле что хранится и как это организовано?

    Если вы хотите понять, как работает это библиотека, что за чем вызывается и тд, то я очень рекомендую использовать вам отладчик (Самый популярный - это xdebug) с какой нибудь удобной gui'шкой (Оная присутствует в phpstorm). Ставите breakpoint и вперед разбираться с порядком вызова того или иного метода, функции и тд.

    Как сразу понимают каким образом использовать чужой код?

    Читаем документацию по этой библиотеке.

    Неужели поддерживать документацию ОПП проще, чем документацию конкретными функциями?

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

    Если бы в будущем был сервис вроде github но для функций и они ставились в php так же просто как установка пакетов apt install функция1 функция2 ..; было бы просто шикардос. Не?

    Вы считаете, что устанавливать библиотеки в php непросто?

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

    Он не пропускал никаких файлов. В комментарии по ссылке он предлагает создать программисту клиентского кода файл с конфигурацией на его усмотрение. Файл конфигурации не имеет никакого отношения к реализации. Программист клиентского кода волен сам решать, как конфигурировать объекты:
    // Так
    $someObf = new SomeClass('this_is_example_api_key');
    
    // Или так
    $someObf = new SomeClass(require('config.php')['api_key']);
    
    // Или, например, так
    $someObf = new SomeClass($config->get('api_key'));
    Ответ написан
    9 комментариев
  • Кто может дать комментарии по поводу кода PHP ООП (Code review)?

    @D3lphi
    Что-то многовато таких вопросов за последние пару дней. Часть замечаний к вашему коду есть в этом ответе. Повторюсь.

    Вы же сами написали:
    класс для работы с многомерными пользовательскими массивами

    но, тем не менее, этот класса делает все, что не лень:
    • Работает с этими самыми массивами
    • Соединяется с базой данных
    • Отправляет запросы к базе данных
    • Занимается обработкой данных

    Не многовато ли для одного класса?
    В итоге, мы получаем богообъект, который "умеет во всё".

    Что у вас за бред написан в методе getInstance()? Зачем бросать исключение, в случае, если инстанс уже был создан.

    if (self::$_instance === null) {
        self::$_instance = new self($id);
    } else {
        throw new Exception("Попытка повторного создания экземпляра Singleton класса");
    }
    return self::$_instance;


    То есть, у вас теряется весь смысл (анти)паттерна синглотон. Получается, я не смогу сделать так:

    $instance1 = treeData::getInstance();
    $instance2 = treeData::getInstance(); // Исключение!

    Есть логика? Я думаю, что нет.

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

    Вы каждый раз повторяете строки с подготовкой запроса, биндингом параметров, отправкой запроса и тд. Не думали, что неплохо бы было написать какую-нибудь обертку и выполнять запросы как-нибудь так:
    $result = $wrapper->select("SELECT * FROM `tablename` WHERE `id` = :id", ['id' => 5]);

    ?


    Абстрактные исключения не бросаем! Создаем свои исключения и наследуемся от них. В своем коде используем только их, дабы можно было легко обработать нужные exception'ы. Текст исключения неплохо бы было писать на английском.

    Имена классов пишем с большой буквы! Скобки после методов и классов пишем на новой строке:
    function example() {
        // Не так
    }
    
    function example()
    {
        // А вот так
    }


    Предлагаю придерживаться общепринятым стандартам оформления кода.

    Старайтесь использовать синглтон в таком виде по минимуму (Или вообще не использовать). Тем более, в данном случае, он вообще не нужен.
    Ответ написан
    6 комментариев
  • Насколько у меня правильный код ООП php?

    @D3lphi
    Здесь плохо всё, к сожалению.

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

    Класс SearchOrder у вас не только выполняет запросы, но еще и работает с данными, хранит состояние этих самых данных, фильтрует данные (strip_tags()). Непорядок. Это все нужно разделять. У вас вообще получаются какие-то богообъекты, которые умеют во все.

    Вы каждый раз повторяете строки с подготовкой запроса, биндингом параметров, отправкой запроса и тд. Не думали, что неплохо бы было написать какую-нибудь обертку и выполнять запросы как-нибудь так:
    $result = $wrapper->select("SELECT * FROM `tablename` WHERE `id` = :id", ['id' => 5]);

    ?

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

    Зачем вы используете свойства, если можно обойтись обычными локальными переменными:
    $this->orderID = (int) strip_tags($orderID);
    $this->column = (string) strip_tags($column);
    $this->value = (string) strip_tags($value);

    ?

    Почему вы стриппите тэги у идентификатора? вы настолько не уверены в том, что влетает в функцию:
    strip_tags($orderID);
    ?

    Если вы не используете php 7 и, как следствие, скалярный тайпхинтинг, то должны делать проверки на тип входящего аргумента. Если что-то не так с типом, бросаем исключение (А не приводим его к нужному)! Например:
    if (!is_string($arg)) {
        throw new InvalidArgumentTypeException('string', $arg);
    }

    Это в идеале. Вы не обязаны это делать, конечно же. Но вот такие проверки делают приложение безопаснее. Хотя, опять же, повторюсь, в 2017 нужно начинать новые проекты на php 7.1+.

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

    Кроме всего прочего, почитайте про стандарты оформления кода. Вы им не следуете.

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

    Желаю успехов!
    Ответ написан
    1 комментарий
  • Атрибуты класса и объектов?

    @D3lphi
    Если вы задаете такой вопрос, значит у вас нет глубокого (или вообще, какого бы то ни было) понимания Объектно ориентированного программирования.

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

    Переменная объекта, как можно догадаться, когда каждый объект должен быть независим. И таких кейсов гораздо больше.

    Вообще, запомните, статика - это глобальное состояние, а глобальное состояние - это плохо. Поэтому очень хорошо подумайте, перед тем, как ее использовать.
    Ответ написан
    Комментировать
  • В чём преимущество автозагрузчика классов?

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

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

    А можно избавиться от строки $obj = new MyClass(); и создавать экземпляр автоматически?

    Нет, нельзя.

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

    @D3lphi
    Каждый класс должен отвечать только за что-то одно. Об этом говорит буква S в аббревиатуре SOLID (single responsibility, единственная ответственность). Следовательно, ни пользователь, ни класс регистрации не "должен" знать что-то про то как происходит загрузка изображений. Эту функциональность нужно выносить в отдельный класс (сервис).
    Ответ написан
    3 комментария
  • Правильно ли я использую класс?

    @D3lphi
    public function setBoss($name)
      {
        $this->boss = $name;
      }


    В данном случае, от этого метода - сеттера нет никакой практической пользы, он не проверяет ничего, не возвращает объект, чтобы можно было производить вызовы методов цепочкой $obj->a()->b(); В данном случае, целесообразнее использовать свойство напрямую.

    Не нужно писать конструкции вот так:
    if (...)
    {
      //
    }

    Пишем так:
    if (...) {
      //
    }

    Это не относится к классам, методам и функциям (в них скобку нужно писать на отдельной строке). Про это все, кстати, написано в PSR. Выберите стиль именования методов, чтобы он был один на протяжении всего кода, а то у вас в одном месте camelCase, в другом - under_scope.

    if(file_put_contents($filename, $content))
        {
          return 'Отчет сохранен';
        }
        else
        {
          return 'Ошибка сохранения';
        }

    Не надо возвращать строку! Возвратите true или false. И запомните: если что-то не так, бросайте исключение!
    Ответ написан