Возможно, это нормально, так и должно быть ? или как архитектурно правильно решать подобное?
Это нормально. Безликие массивы становятся осмысленными сущностями. Такой код становится проще понимать и поддерживать.
Используемый вами подход называется data transfer object (DTO). Широко распространенная практика. DTO отлично сочетается с иммутабельностью, которая присутствует в ваших классах.
Единственная претензия только к тотальному отсутствию комментариев. Неплохо было бы описать классы и каждый параметр на предмет что он означает, зачем нужен и где его можно использовать.
В результате, на каком-то уровне приложения, происходит выборка, а дальше создаются все необходимые объекты, и внедряются друг в друга. (кстати, как называется этот слой приложения, и в чьей зоне ответственности эта задача ?)
Называется ORM. Находится в ответственности ORM слоя/фреймворка.