«phpClub» — архив тем ("тредов"), посвящённых изучению PHP и веб-технологий.
https://github.com/kydva/HotelOOP Аноним 2020/06/29 22:47:39  №1737441 1
>>1722087 →

> Это ведь так должна выглядеть композиция
По идее, да.

У тебя неудачно сделано то, что информация о бронях хранится в 3 копиях. Это сильно усложняет работу с кодом, так как любое изменение надо делать 3 раза, очень легко где-то ошибиться, и в итоге получить расхождение в данных. Данные о бронях стоит хранить в одном месте, это может быть, например Hotel или BookingService. При этом при желании можно прокидывать ссылку на них в Room, чтобы он мог знать о том, когда он забронирован, хотя по моему, проще без этого. Дублирование данных надо избегать.

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

> пишем пользовательскую функцию сравнения по уникальному номеру для array_udiff

Объекты можно сравнивать на равенство с помощью ===. Это условие сработает, только если справа и слева ссылка на один и тот же объект. То есть объект без всяких номеров обладает идентичностью. А вот == будет сравнивать не идентичность, а поля объекта и тут меньше подходит.

> return ($freeRooms[0]->getCapacity() >= count($guests))

Здесь будет ошибка, если массив $freeRooms пуст.

> //Если в этот раз не вышло разместить никого, пытаемся сначала разместить на одного гостя меньше

Тут по-моему ошибка: мы удаляем одного гостя из массива и ему ничего не будет предложено.

> Все функции я протестировал в самых разных ситуациях дебаггером

Это хорошо, что ты умеешь использовать отладчик, но по идее код лучше тестировать автоматическими тестами. Хотя они могут потребовать некоторое время на написание, зато потом после любых правок можно их запустить, и убедиться, что код не сломался. Если тебе интересна эта тема, то можешь попробовать написать автотесты для своей гостиницы. Вот пара ссылочек в помощь:

- урок про то, что такое и как писать автотесты: https://gist.github.com/codedokode/a455bde7d0748c0a351a

Если хочется посмотреть на реальные автотесты, то могу посоветовать компонент Symfony HttpFoundation: https://github.com/symfony/http-foundation . Он содержит классы, соответствующие HTTP-запросам и ответам (протокол HTTP используется в работе сайтов: браузер при открытии страницы посылает на сервер запрос, и получает ответ. Данная библиотека ничего никуда не отправляет, но сождержит классы, хранящие информацию о запросах и ответах). И там же в папочке Tests есть тесты для этих классов.

Если хочется разобраться в ООП поглубже, то могу предложить сделать классы для представления математических выражений вроде 2x + 3y + 7 (там получится дерево из объектов Сумма, Произведение, Переменная, Константа), а затем реализовать упрощение выражений, например 2x + y + 3x -> 5x + y. Задача выглядит простой по описанию, но позволит изучить деревья, AST, паттерн Visitor, трансформацию деревьев выражений.

Если ни тесты, ни выражения делать не хочется, можно браться за задачу про список студентов.
Ответы: >>1738567
Аноним 2020/06/30 23:05:53  №1738567 2
image.png (28, 418x447)
447x418
>>1737441
Спасибо что ответил. Не хотел второй раз дергать, тем более что последним временем побольше угорел по линуксу, базам данных и html/css/js, почти за пхп забыв. Хотя вчера вот завершил раздупление над материалом из этой https://github.com/codedokode/pasta/blob/master/soft/web-server.md и сопутствующих страниц о http, шаблонизации и прочем, по идее сегодня должен был бы начинать над списком студентов работать, но я все еще играюсь с базами данных на sql-ex.
Рецензию понял- принял. Хотя нет, кое-что таки не понял:
>Это сильно усложняет работу с кодом, так как любое изменение надо делать 3 раза, очень легко где-то ошибиться, и в итоге получить расхождение в данных.
Это всё же само собой проделывается в функции register() класса Hotel. Хотя это, конечно, не отменяет того, что можно было сделать получше. Алсо, иногда появляется желание инкапсулировать скрыть некоторые методы от всех классов кроме какого-то одного, для использования которым они и созданы. Например, в этом случае совсем нежелательно чтобы функции регистрации гостя или комнаты были доступны отдельно от общей функции регистрации. В векторе вроде тоже были схожие ситуации. Значит ли такое желание то, что я делаю что-то не так? Ведь насколько я понимаю, такой возможности не существует помимо как в наследовании, а значит быть ее и не должно.
>Тут по-моему ошибка: мы удаляем одного гостя из массива и ему ничего не будет предложено.
Значение переменной $notHostedGuests ведь не меняется в этом случае. Функция сначала попытается подобрать комнату для меньшего количества гостей, после чего отнимет из $notHostedGuests это количество при успехе, и уже будет пытаться найти комнату для оставшегося количества гостей посредством вырезания в новый массив количества гостей из $guests, равного $notHostedGuests. По факту функция раз за разом размещает тех самых гостей в другие комнаты, но это значения не имеет, так как в возвращаемом функцией массиве не указано каких конкретно гостей куда поселить, указано лишь количество для комнаты. За то каких гостей куда селить отвечает другая функция - registerInBestRooms и так далее. Так или иначе, это всё равно лишь полурабочий жадный алгоритм.
На счет автотестов - планирую их изучать попозже, это всё же не самая главная вещь, но знаю что необходимая. Начну наверное со студентов, хотя твоя задачка меня заинтересовала, но не совсем понял ее. Насчет упрощения выражений понятно, а что ты имеешь в виду под представлением выражения? Типо на вход какому-то менеджеру через функцию попадает строка вида "2x + 3y + 7", а он раскладывает ее на что-то вроде пикрил? Как должна представляться древовидность? С помощью аггрегации, в свойстве объекта должен быть массив с вложенными в него объектами или как?
Ответы: >>1740405
Аноним 2020/07/02 23:00:26  №1740405 3
>>1738567

>>Это сильно усложняет работу с кодом, так как любое изменение надо делать 3 раза,

> Это всё же само собой проделывается в функции register() класса Hotel

Это сейчас у тебя только одно действие - регистрация. А когда пойдут изменения в бронях, удаление броней, тебе придется каждую операцию в трех местах делать. Потому надо избегать дублирования. Это усложняет код, и создает вероятность расхождения списков из-за ошибок.

> Алсо, иногда появляется желание инкапсулировать некоторые методы от всех классов кроме какого-то одного, для использования которым они и созданы.

В PHP для этого ничего нет, в Си++ есть такое понятие, как "классы-друзья", которые могут лезть в защищенные поля друг друга. Но в общем в ООП такой подход не распространен. Возможно, стоит менять что-то в архитектуре. Вот, например, если не хранить в Госте список броней, то и метод register() в нем будет не нужен.

> Значение переменной $notHostedGuests ведь не меняется в этом случае. Функция сначала попытается подобрать комнату для меньшего количества гостей, после чего отнимет из $notHostedGuests это количество при успехе, и уже будет пытаться найти комнату для оставшегося количества гостей

Да, верно.

> а что ты имеешь в виду под представлением выражения? Типо на вход какому-то менеджеру через функцию попадает строка вида "2x + 3y + 7", а он раскладывает ее на что-то вроде пикрил? К

Для начала, можно создавать выражение руками, без парсера:

$expr = new Sum(new Constant(10), new Variable('x')); // 10 + x

А потом, если будет желание, прикрутить парсер.

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

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

> Как должна представляться древовидность?

Дерево - это структура, которая состоит из узлов, начинается с корневого узла, и у каждого узла могут быть узлы-дети.

> С помощью аггрегации, в свойстве объекта должен быть массив с вложенными в него объектами или как?

Да, можно так.