Scala: шаблон проектирования для объекта / средства визуализации для пользовательского интерфейса - PullRequest
0 голосов
/ 20 декабря 2018

Какой был бы хороший дизайн, чтобы иметь renderer и object.

Я сделал несколько попыток, но мой код сейчас действительно ужасен.

Допустим, у меня есть класс room и класс, который должен обрабатывать его рендеринг.

  • Кому следует звонить renderer.render(room) или так должно быть?
  • Должен ли я иметь world.renderRoom()?
  • Или я должен иметь room.renderWith(renderer)?

Как мне создать простой модульный тест, например renderer.render(room, userInteraction)

А какой должен быть возврат?

world.renderRoom().interact()....?

Как вы можете сказать, я понятия не имею, что делать, ха-ха.

У меня есть несколько лет опыта написания программного обеспечения, но я пробую ScalaZ и пытаюсь быть более functional-programming -подобным;что ново для меня.

Спасибо

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

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

Не добавляйте код рендеринга в объекты данных, потому что это нарушает разделение интересов.Классический пример ОО класса Shape с методом draw отлично подходит для обучения, но он объединяет данные о форме (например, число сторон) с определенным способом ее рисования.Вместо этого создайте функцию render(s: Shape), которая использует данные в Shape для рисования нужным образом (2D, 3D-заливка, список координат и т. Д.).

Создайте код renderфункциональный, чтобы он возвращал визуализированные данные, а не вызывал библиотеку рендеринга как побочный эффект.Библиотека рендеринга должна быть функциональной и возвращать результаты рендеринга, а не рисовать непосредственно на экран.

Передать библиотеку рендеринга в функцию render (в качестве параметра implicit) вместо использования глобального объекта.,Это позволяет вам протестировать рендеринг с помощью фиктивного рендера, и в любом случае это более гибкий дизайн.Но вам все равно могут понадобиться разные функции render для разных устройств вывода или стилей.

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

Создайте все изображение вфункциональным способом, а затем выполнить одну нефункциональную операцию для отображения нового изображения (путем замены текущего изображения).

Использование взаимодействия с пользователем для создания измененной сцены с обновленным room, а затем повторная визуализациявся сцена.

TL; DR

val room = Room(width, length, height)
val room3D = render(room, render3D)
val house = compose(room3d, ..., compose3D)

screen.display(house)
0 голосов
/ 20 декабря 2018

Рендеринг экрана не является чистой функцией, поскольку имеет побочные эффекты.читать о IO монаде .

Вы обнаружите, что большинство (если не все) примеры относятся к println и readln, но применяется тот же принцип.В контексте скалаза взгляните на ZIO .

, если, как предполагает Тим ​​в комментарии, рендер - это чистая функция, тогда я полагаю, что рендер является функцией рендера модели (комната) и состояние комнаты - это кратность действий newRoomState=actions.foldLeft(oldRoomState)(state,action => someFunction(s,a)) (покрасить стену, добавить диван в любом случае), см. SAM .И мир, который принимает рендеры (flatMaps / уменьшение в течение нескольких рендеров ?!) - это та часть, которая требует монады ввода / вывода)

...