maxcom/lorsource — comment on commit bc3f80ddebd5dc319bffa037d5f124e10a38dbf1
File:  line 0
By slavaz:

> кстати, да, я же ее и раскопал, только насколько это принципиально, ведь одну маленькую строчечку c <% %> можно?

принципиально или нет, но более правильно всё-таки код выносить в контроллеры. В jsp по возможности не должно быть логики, кроме стандартных JSTL-тегов и своих самопальных тегов (со своими контроллерами).

Вообще, как меня учили, web-приложение должно строиться следующим образом:
1) UI-слой - взаимодействие с пользователем, формы ввода, JS, AJAX и т.д.. тут может быть JSP, JSTL, FreeMarker и т.д. . Никаких Java-вставок. Логики не должно быть по одной простой причине: вместо JSP вполне можно будет подсунуть REST-слой...
2) Контроллеры. У них есть только две цели:
* получить данные форм с UI, преобразовать их в доменные объекты и передать сервисам;
* запросить доменные объекты у сервисов, при необходимости преобразовать в данные web-форм и отдать UI
Никакой другой логики в контроллерах быть не должно. Контроллеры могут обращаться только к сервисам, слой DAO для них должен быть невидим.
3) Сервисы. Это слой абстракции, в котором и содержится основная логика приложения. Принимаются данные от контроллеров, при необходимости происходит обращение к DAO-слою, происходят вычисления и преобразования согласно алгоритмов (хотел тут написать - согласно бизнес-логике:) ). Короче сервисы - это "сердце" приложения. Сервисы оперируют классами данных, называемыми доменными. Доменные классы - это классы, предназначенные для обмена информацией между сервисами, контроллерами и, возможно, UI. то есть domain-классы - это "кровь" приложения. Если часть функционала делегируется в SQL-процедуры и в SQL-функции, то сервисы(методы сервисов) выступают как бы шлюзами для соответствующих методов DAO-классов, при этом контроллера всё также обращаются только к сервисам и никогда - к DAO-объектам. Сервисы могут вызывать другие сервисы и различные DAO-классы.
4) DAO-классы. Предназначены для получения и сохранения информации в/из хранилищ данных (обычно СУБД, но не всегда). Могут также предоставлять доступ к внешним алгоритмам (будь то хранимые процедуры или функции SQL или будь то система построения правил типа Drools). В этом случае внешние алгоритмы рассматриваются тоже как источники данных (либо модифицирующие запросы, если алгоритмы ничего не возвращают, но меняют состояние данных в хранилище). Для отражения данных хранилища используются DTO-классы, которые повторяют структуру полей SQL-запроса; либо содержат необходимые поля для INSERT- запросов, либо содержат поля и conditions для UPDATE-запросов; либо только conditions для DELETE запросов; либо необходимые входные и выходные параметры для внешних алгоритмов. В любом случае, работа DAO-слоя должна "сглаживать" особенности хранилищ данных или внешних алгоритмов. Преобразование DTO-классов в доменные происходит обычно в сервисах (один доменный класс может состоять из множества DTO-классов или из одного доменного класса могут получаться различные DTO-классы в зависимости от вызываемого метода DAO-класса).

Вот по такой схеме в нашей конторе (www.epam.com) коммерческие проекты и делаются. В чём-то она избыточная и трудоёмкая, но зато очень проста в сопровождении, проста в обвязывании тестов, проста в разработке новых фич. Эта схема выстрадана поколениями программеров. Я пытаюсь применить это уже и в движке ЛОРа, но ка выяснилось, не всё подходит :). Мои профессиональные навыки противятся принятой в ЛОРовском движке схеме (если честно, то схемы особо-то и нет, есть обрывки разных схем, начиная от самых ранних, когда спринга ещё не было).

Вот наличие <%%> вставок - это и есть наследие безспринговой схемы. Поэтому лучше от такого избавляться. Спринг позволяет упорядочить исходники, упрощая сопровождение и написание тестов (даже контроллера можно тестировать, а <%%> вставки вряд ли).

> я не вижу пока особого сильного profit-а, с другой стороны стараюсь не использовать<% %> как завещают django-разработчики

Я не в курсе, что там завещают django-девелоперы, но без таких вставок переход на другую шаблонную систему (например, на FreeMarker) не составит труда. Фримаркер взял так, от балды, но по опыту использования его в одном коммерческом проекте, отзывчивость фримаркеровских шаблонов в разы отличается от стандартных JSP. А перейти, или вернее, дополнить, вполне можно будет и REST-слоем.

Пользуясь случаем, попробую обрисовать схему ЛОРовского движка:
1) разбивка на пакеты по назначению (topic, section,..), а не по типу (service, controller, dao,...)
2) отказ от DTO-объектов. Данные из хранилища напрямую вносятся в доменные классы. При этом классы иммутабельны, что подразумевает передачу от контроллеров к сервисам не доменных классов, а тучи параметров в методах.
3) отказ от интерфейсов. Впрочем, для тестирования сервисов интерфейсы DAO-классов нужны, чтобы можно было связывать MOCK-объекты. Когда понадобится тестировать контроллера, то нужны будут и интерфейсы сервисов... ;)

Макс, Ильдар, если есть ещё какие видения схем разработки движка - давайте обсудим. Приводить к единому знаменателю надо в любом случае, но вот в какой форме оно будет - надо решить.