как лучше провести рефакторинг двух классов с большим количеством условной логики? - PullRequest
3 голосов
/ 20 июля 2009

У меня есть класс Event, который содержит время начала и окончания события. Каждый объект Event может иметь несколько связанных объектов ChildEvent, представляющих каждое повторение родительского события. Каждый из этих классов должен выполнить свое действие в зависимости от того, как они редактируются, например,

Удаление только одного события:

  • Событие: сделайте первого потомка родителем всех остальных потомков перед удалением
  • ChildEvent: просто удалите как обычно

Удаление события и всех последующих событий:

  • Событие: удалить все дочерние события, а затем удалить себя
  • ChildEvent: удалить всех будущих братьев и сестер, а затем удалить себя

Редактирование только одного события:

  • Событие: сделать первого потомка родителем всех остальных потомков, затем обновить
  • ChildEvent: обновлять себя как обычно

Редактирование события и всех последующих событий:

  • Событие: обновите все дочерние события, затем обновите себя
  • ChildEvent: обновите всех будущих братьев и сестер, затем обновите себя

В настоящее время я достигаю этого, проверяя условия и предпринимая соответствующие действия, но это начинает становиться грязным (есть и другие условия со связанным поведением). Мне любопытно узнать, как с этим справятся более опытные программисты (я использую ruby). Есть идеи?

Ответы [ 3 ]

3 голосов
/ 20 июля 2009

Звучит как случай для шаблона спецификации для инкапсуляции вашей логики

0 голосов
/ 20 июля 2009

Я предлагаю попробовать другую объектную модель. Вместо Events и ChildEvents вы можете рассматривать его как EventType s и Event s.

EventType  # Has many Events
---------
name
# ...

Event      # Belongs to EventType
-----
event_id
start_time
end_time
# ...

Тогда ваши операции редактирования будут значительно упрощены.

Найти предыдущее событие ...

Event.find(:first, :conditions => [
  'event_type_id = ? AND start_time > ?',
  event.type.id,
  event.start_time],
  :order => 'ASC'
)

Удалить событие и все последующие события этого типа ...

events_to_delete = Event.find(:all, 
  :conditions => [
    'event_type_id = ? AND start_time >= ?', 
    event.event_type.id,
    event.start_time
  ])

Event.destroy( all_events_to_delete.map { |event| event.id } )
0 голосов
/ 20 июля 2009

Почему бы вам просто не связать события в виде двусвязного списка?

Событие будет иметь слот previous и next (ноль, если первый или последний из цепочки).

Удаление только одного события (delete):

  • установить слот previous события next на слот previous этого события
  • установить слот next события previous на слот next этого события
  • удалить это событие

Удаление события и всех последующих событий (delete-all):

  • Удалить это событие
  • набор next слот previous Событие в ноль
  • Рекурс на next Событие
  • до next ноль

Редактирование только одного события (edit):

  • изменить это событие
  • установить previous слот next Событие на previous слот этого события
  • установить next слот previous Событие в next слот этого события

Редактирование события и всех последующих событий (edit-all):

  • если начальный вызов, установите next слот previous Событие на ноль
  • изменить это событие
  • Рекурс на next Событие
  • до next ноль
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...