Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dive into DDD // Albert

Dive into DDD // Albert

Albert Gazizov's Keynote

04/03/2014

Droid Labs

April 06, 2014
Tweet

More Decks by Droid Labs

Other Decks in Programming

Transcript

  1. ActiveRecord class Contact < ActiveRecord::Base include Extensions::Sluggable MAX_IMAGE_SIZE = configatron.max_image_size

    SMALL_IMAGE_WIDTH = configatron.contact.small_image_width has_many :parts, dependent: :destroy has_many :emails has_one :contact_stat belongs_to :user has_one :company attr_accessible :first_name, :last_name, :position, :created_on, :small_image, :image, :additional_image, :image, :parts_attributes, :group_list :tag_list, :user_id, :slug, :old_slug accepts_nested_attributes_for :parts, allow_destroy: true mount_uploader :small_image, SmallImageUploader mount_uploader :image, ImageUploader acts_as_taggable_on :aliases, :tags slugize :name validates :created_on, :group_list, presence: true validates :fiirst_name, presence: true, uniqueness: true ...
  2. Use Cases •  Регистрация в системе •  Создание проекта • 

    Создание таска •  Изменение статуса таска •  Комментирование таска •  ...
  3. Создание таска class TaskTracker::Service::CreateTaskService attr_reader :accessor, :tasks_repository, :task_builder def initialize(accessor,

    tasks_repository, projects_repository, project_members_repository) @tasks_repository = tasks_repository @task_builder = TaskTracker::Builders::TaskBuilder.new( accessor, projects_service, project_members_repository ) end def create(attributes) task = task_builder.build(attributes) tasks_repository.put(task) endend
  4. class Entities::Task attr_accessor :id, :title, :description attr_reader :status, :author_id, :project_id,

    :subtasks def initialize(title:, description: nil, project_id:, author_id:) Utils::ArgsValidator.not_blank!(title, :title) Utils::ArgsValidator.not_nil!(project_id, :project_id) Utils::ArgsValidator.not_nil!(author_id, :author_id) @title, @description, @project_id, @author_id, @subtasks = title, description, project_id, author_id, [] end def change_status(new_status) raise Common::Errors::InvalidParameter, "status can't be set to '#{new_status}'" unless @status.allowed_next_status?(new_status) @status = new_status end def title=(title) Utils::ArgsValidator.not_blank!(title, :title) @title = title end def id=(id) Utils::ArgsValidator.immutable!(@id, id, :id) @id = id end def build_subtask(title:) Entities::Subtask.new(title: title).tap do |subtask| subtasks << subtask end endend
  5. class TaskTracker::Builders::TaskBuilder attr_reader :accessor, :projects_repository, :project_members_repository def initialize(accessor, projects_repository, project_members_repository)

    @accessor, @projects_repository, @project_members_repository = accessor, projects_repository, project_members_repository end def build(title:, description: nil, project_id:, subtasks: []) task = Entities::Task.new(title: title, description: description, project_id: project_id, author_id: accessor.id) subtasks.each do |title:| task.build_subtask(title: title) end ensure_project_exists!(project_id) ensure_accessor_is_project_member!(project_id) task end private def ensure_project_exists!(project_id) unless projects_repository.exists?(id: project_id) raise Common::Errors::InvalidParameter, "project with id '#{project_id}' doesn't exists" end end def ensure_accessor_is_project_member!(project_id) unless project_members_repository.exists?(project_id: project_id, member_id: accessor._id) raise Common::Errors::AuthorizationError, "you don't have access to the project '#{project_id}'" end endend
  6. class Repository::TasksRepository attr_reader :tasks def initialize @tasks = {} end

    def put(task) task.id = tasks.size tasks[task.id] = task task end def find(id) tasks[id] end def delete(task) tasks.delete(task.id) endend
  7. Обязанности пограничного слоя •  Кастинг params •  Синтаксический анализ params

    •  Валидация* •  Вызов сервиса БЛ •  Сериализация ответа сервиса в DTO(хеш)
  8. TasksBoundary class Boundary::TasksBoundary attr_reader :tasks_repository, :projects_repository, :project_members_repository def initialize(accessor) tasks_repository

    = Repository::TasksRepository.new projects_repository = Repository::ProjectsRepository.new project_members_repository = Repository::ProjectMembersRepository.new end def create(params) params = Boundary::Casters::Tasks::CreateFormCaster.cast!(params) create_task_service = TaskTracker::Service::CreateTaskService.new(accessor, projects_repository, project_members_repository) task = create_task_service.create(params) Boundary::Serializers::TaskSerializer.serialize(task) endend
  9. Caster & Serializer class Boundary::Casters::Tasks::CreateFormCaster include Hcask::Caster attributes do string

    :title string :description, optional: true array :subtask, each: :hash, optional: true do string :title end endend class Boundary::Serializers::TaskSerializer include ActiveSerializer::ObjectSerializer serialization_rules do attributes :id, :title, :description, :status resources :subtasks do attributes :title end endend