[WIP] Выразительность в Rails. Формулировка проблемы.


Что такое выразительность? Позволю себе перефразировать одно из определений:

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

Определение легко обобщается и на случай ЯП + framework. Выразительность субъективна, она зависит от разработчика, от степени абстрактности его мышления.

Популярность RubyOnRails показывает, что фреймворк достаточно выразителен для веб-программирования (по крайней мере, для классической модели). В качестве одной из причиной выбора Rails часто указывается легкость начала работы. Многие проходили стандартное упражнение по созданию блога за 15 минут и, надо признать, код выглядит весьма понятно.

Rails реализует шаблон MVC, предоставляет концепцию ресурсов, но при этом все связи обеспечиваются исключительно схемой наименования классов. Технически фреймворк накладывает ограничения только на распределение классов по файлам. Из-за этого каждый раз необходимо уточнять, что params[:id]в ArticleController — это именно идентификатор Article, а params[:id] в UsersController — это id пользователя. В какой-то степени этой проблеме адресованы InheritedResources и DecentExposure, но идея обобщения контроллеров так и не получила развития.

Далее, почему бы Article не просто знать, что в нем есть указатель на User, но и знать, что этот указатель определяет её создателя? Разработчик может прописать это понятным для себя способом, через

Article.belongs_to :creator, class_name: “User”

Но это будет служить лишь удобству остальных разработчиков. Системе все равно придется объяснять что такое @user.articles и вручную вставлять проверки каждый раз, когда нужно убедиться, что пользователь обладает достаточными правами для управления своими статьями.

Отдельная тема — пользовательский контент. В огромном числе ситуаций на сайте есть пользователи и эти пользователи создают контент. И возникают рутинные задачи по регистрации пользователей, управлению их профайлами и их контентом. А как было бы приятно делать как-то так:

defactor :User
defcontent :Article

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

Хаос начинается там, где заканчиваются соглашения. Не случайно бытует мнение, что rails проект после нескольких лет разработки превращается в мешанину. Фреймворк не предоставляет стандартизированные средства описания предметной области, код пишется исходя из уровня понимания разработчика и для возрастания путаницы достаточно только изредка добавлять/удалять людей из проекта. Плюс необходимо учитывать, что со временем степень погружения в предметную область увеличивается и разработчик корректирует терминологию.

Вопрос как писать расширяемый приложение выходящее за пределы CRUD открыт. Как вариант — покрытие слоем сервисов, дробление сервисов посредством CQRS, использование DCI. Я склоняюсь к тому, что необходимо тщательно прорабатывать ubiquitous language, расширяя язык терминами предметной области и уходя от примитивных абстракций типа MVC. Также интересные возможности открывает кодогенерация, например, много ли вы знаете соглашений в Rails которые нельзя формализировать? А если можно формализировать, то почему бы не автоматизировать…

Полезные ссылки

  1. Оби Фернанденс тоже думал об этом http://www.jroller.com/obie/entry/more_about_ontologies
  2. сборник статей про архитектуру https://github.com/padwasabimasala/hexagonal-ruby
  3. одна интересная история
    http://naildrivin5.com/blog/2014/05/27/rails-does-not-define-your-application-architecture.html