Вы, кажется, спрашиваете о множестве разных вещей, которые затрудняют ответить, за исключением очень общих способов.
Не добавляйте код рендеринга в объекты данных, потому что это нарушает разделение интересов.Классический пример ОО класса 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)