Вопрос о дизайне ООП

Я - относительно новое ООП использования в PHP. Этому помогают очень в организации и обслуживании моего кода, но я хотел бы поправиться при разработке моих классов и использовании ООП так эффективно, как я могу. Я считал Банду Четырех книг Шаблонов разработки, но все еще нуждаюсь в некоторой помощи. После создания нескольких небольших приложений вот одна вещь, через которую я продолжаю бежать.

Скажем, я создаю приложение, которое отслеживает информацию о приеме для школы.

Путем я в настоящее время приближался бы, этому нужно было назвать класс student, и методы в том классе для CRUD на записи отдельного студента. Кажется логичным, что у меня был бы метод конструктора для этого класса, который взял student_id как аргумент, таким образом, я мог сослаться на него из объекта для всех тех различных операций CRUD.

Но затем, в то время как я продолжаю создавать приложение, я натыкаюсь на ситуации, где мне нужно к выполнению запросов, которое возвращает несколько студентов. Например, что-то как, get_all_students_from_grade($grade), get_dropdown_of_all_students(), и т.д. Эти методы не относятся всего к одному студенту, таким образом, это кажется нечетным, что у меня были бы они как методы в моем student класс, так как я инстанцировал объекта с одним student_id в памяти. Очевидно, я могу заставить его проложить себе путь, но кажется, что я 'делаю его неправильно'. Что лучший способ состоит в том, чтобы приблизиться к этому?

6
задан Matthew 1 January 2010 в 18:26
поделиться

8 ответов

Отделите класс student (который является классом домена) от операций над ним (бизнес-логика или доступ к данным, в зависимости от случая), например:

  • student - объект домена содержит только данные
  • student_service или student_dao (Объект доступа к данным) - выполняет операции

Иногда это считается нарушением инкапсуляции, но это общепринятая лучшая практика.

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

.
4
ответ дан 10 December 2019 в 00:39
поделиться

Разбейте его на два класса:

  1. student
  2. student_repository

Ваш ученический класс ничего не знает о том, как он хранится по отношению.

$students = student_repository.get_all_students_from_grade($grade)
4
ответ дан 10 December 2019 в 00:39
поделиться

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

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

Таким образом, вы избегаете запуска одного SQL-состояния для каждого изменения (вы все еще работаете с набором строк вместо него) и в то же время предлагаете доступ к отдельным объектам (поддерживая индекс к текущему местоположению в кэше, и позволяете этому "указателю" быть расширенным приложением, как он вызывает методы вашего класса)

.
1
ответ дан 10 December 2019 в 00:39
поделиться

Всегда есть отправная точка. В вашем случае это было бы то, откуда вы забираете учеников (т.е. из школы, класса и т.д.).

$class = new Model_Class;

$students = $class->students;

foreach($students as $student)
{
    print $student->name. ' is in class '. $class->name;
}
1
ответ дан 10 December 2019 в 00:39
поделиться

Вы можете пойти по заводскому методу и попросить фабрику решить, каким должен быть ID нового ученика.

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

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

.
0
ответ дан 10 December 2019 в 00:39
поделиться

Как сказал Нил в своем комментарии (не уверен, почему мы не ответили на этот вопрос), наверное, вам также следует пройти курс и занятия в школе . Вы можете иметь специфические для школы методы (получение всех учеников в данном классе, с заданным количеством пропущенных дней и т.д.) в School и специфические для данного курса методы (все ученики в курсе с определенным классом и т.д.) в классе Course.

Вы правы, думая, что в стандартном CRUD вы не хотите давать классу, представляющему отдельное лицо (т.е. Student class), ответственность за загрузку кратных единиц себя самого. С другой стороны С другой стороны , если бы вы выбрали более ActiveRecord стиль загрузки данных (который использует Ruby on Rails), то вы на самом деле сделали бы все методы загрузки Student статическими на самом классе Student. Это зависит только от того, как вы хотите его стилизовать, что отчасти зависит от того, насколько сложной будет становиться ваша модель данных.

.
0
ответ дан 10 December 2019 в 00:39
поделиться

Сделать их методами класса на Student.

.
-1
ответ дан 10 December 2019 в 00:39
поделиться

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

Я решил эту проблему, выполнив следующие действия

1.) Создайте класс, имеющий три формы создания экземпляров,

одну, где она новая

$myStudent = new $Student();

, другую, в которой вы знаете идентификатор, но нуждаетесь в данных идентификаторов

$myStudent = new $Student($student_id);

и другой, где у вас уже есть данные в ассоциативном массиве

$data = array('id'=13,'name' => 'studentname', 'major' => 'compsci');
$myStudent = new $Student($data['id'], $data);

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

вот конструктор для такого класса:

public function __construct($id=FALSE, $data=FALSE)
{
    if(!$id) $this->is_new = true;
    else if($id && !$data) $this->get_data_from_db($id);
    else if($id && $data) $this->set_data($data);

}
1
ответ дан 10 December 2019 в 00:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: