Использование "точных" названий и разделенных классов
От: Аноним  
Дата: 01.09.08 14:44
Оценка:
Здравствуйте.

Есть несколько небольших проектов, которые разрабатывались как плагины к одному приложению. У меня появились несколько субъективных проблем


Почему субъективные — потому что для моего коллеги, вместе с которым мы делаем эту работу, это не видится проблемой.

Именование классов: в одном проекте у нас есть FilterEntity, в другом — ConditionEntity. Как-то это немного путает имхо, когда дальше в некой логике необходимо оперировать понятием ConditionEntity, который на самом деле FilterEntity. Да и слегка различаются наборы свойств (сейчас решено наследованием от FilterEntity). Сами по себе классы — просто контейнеры для данных.

Что касается разделения классов, то здесь я просто предлагал использовать разделение на GUI и BL. Сейчас диалоги работают напрямую с объектами, т.е. передаем диалогу ссылку на некий объект FilterEntity и диалог сам его изменяет, заполняет. Наверное, само по себе это уже не очень хорошо. Плюс, вышеназванная проблема именования — просто так теперь класс этого объекта не переименовать, т.к. все предыдущие проекты завязаны на старом названии.

Я бы сделал так: создал бы класс FilterEntityGui, который выставляет наружу только самые необходимые свойства для конкретного диалога FilterDialog. И работает данный конкретный диалог с этим классом. А все остальные пользователи этого диалога используют выходные данные по своему усмотрению.

Просто интересно, сталкивался ли кто с таким? Может, зря я паникую
Re: Использование "точных" названий и разделенных классов
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 02.09.08 07:01
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Что касается разделения классов, то здесь я просто предлагал использовать разделение на GUI и BL. Сейчас диалоги работают напрямую с объектами, т.е. передаем диалогу ссылку на некий объект FilterEntity и диалог сам его изменяет, заполняет. Наверное, само по себе это уже не очень хорошо.


Само по себе это ни хорошо, ни плохо.

А>Плюс, вышеназванная проблема именования — просто так теперь класс этого объекта не переименовать, т.к. все предыдущие проекты завязаны на старом названии.


Значит, старые проекты тоже должны обновиться. Или "заморозиться".

А>Я бы сделал так: создал бы класс FilterEntityGui, который выставляет наружу только самые необходимые свойства для конкретного диалога FilterDialog. И работает данный конкретный диалог с этим классом. А все остальные пользователи этого диалога используют выходные данные по своему усмотрению.


Пока что маловато обоснований для прослойки. Зачем она? Если только для того, чтобы ограничить интерфейс Filter — то неправильно ставишь задачу. Прослойку имеет смысл делать только ради того, чтобы проще было решать какие-то задачи. Какие?

А>Просто интересно, сталкивался ли кто с таким? Может, зря я паникую


Да нет, вроде не зря. В именах, ИМХО, путаница получается.

Попробуйте для начала перепроектировать структуру классов, только выкиньте эти дурацкие приписки Entity — любой объект и так Entity. Получится, как минимум, Filter и Condition. Сразу вылезает интересное наблюдение: Filter включает в себя Condition и какое-то поведение по отношению к "фильтруемому" объекту. По крайней мере, с точки зрения семантики человеческого языка.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[2]: Использование "точных" названий и разделенных классов
От: a.coder Россия  
Дата: 02.09.08 09:17
Оценка:
Здравствуйте, Геннадий Васильев, Вы писали:

ГВ>Здравствуйте, Аноним, Вы писали:


А>>Что касается разделения классов, то здесь я просто предлагал использовать разделение на GUI и BL. Сейчас диалоги работают напрямую с объектами, т.е. передаем диалогу ссылку на некий объект FilterEntity и диалог сам его изменяет, заполняет. Наверное, само по себе это уже не очень хорошо.

ГВ>Само по себе это ни хорошо, ни плохо.
Подумал, согласен.

А>>Плюс, вышеназванная проблема именования — просто так теперь класс этого объекта не переименовать, т.к. все предыдущие проекты завязаны на старом названии.

ГВ>Значит, старые проекты тоже должны обновиться. Или "заморозиться".
Тоже вариант, но пока до заморозки рановато. Приходилось вносить незначительные изменения во все проекты. Есть шансы что еще придется.

А>>Я бы сделал так: создал бы класс FilterEntityGui, который выставляет наружу только самые необходимые свойства для конкретного диалога FilterDialog. И работает данный конкретный диалог с этим классом. А все остальные пользователи этого диалога используют выходные данные по своему усмотрению.

ГВ>Пока что маловато обоснований для прослойки. Зачем она? Если только для того, чтобы ограничить интерфейс Filter — то неправильно ставишь задачу. Прослойку имеет смысл делать только ради того, чтобы проще было решать какие-то задачи. Какие?

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

Да, в первую очередь хотелось бы ограничить интерфейс Filter GUI. Как было в примере, в 3 разных проектах используется один и тот же диалог, но из-за того, что в нем используется класс сущности для извлечения данных, неудобно эту саму сущность изменять.

Попробую описать свою проблему конкретным примером

Структура проектов такая:
1. PluginProject1 (enum FilterTypes1)
2. PluginProject2 (enum FilterTypes2)
3. PluginCoreProject3 (BaseFilter, KeywordsFilterDialog, ListFilterDialog)

В PluginCoreProject3 есть классы фильтра BaseFilter и диалогов KeywordsFilterDialog, ListFilterDialog.
У фильтра BaseFilter есть поле Type — типа int.

public class BaseFilter
{
  private int type;
  public int Type {get; set;}

  ...
}

public class KeywordsFilterDialog : Form
{
  public KeywordsFilterDialog(BaseFilter filter)
  {
    ...
  }
}


Проекты PluginProject1 и PluginProject2 используют BaseFilter, но Type трактуются в каждом по-своему. Для этого заведены enum'ы FilterTypes1 и FilterTypes2. В коде же используются преобразования типа:
  FilterTypes1 ft = (FilterTypes1) myFilter.Type;

и, соответственно, обратые преобразования:
  BaseFilter filter = filters.GetFilterByType( (int) FilterTypes1.Books);

Такие конструкции неудобны, когда дальше в логике приходится интенсивно использовать Filter.

Была идея сделать BaseFilter generic'ом, которому передавался бы свой enum в каждом проекте, но тут я уперся в диалоги. Диалоги в своих конструкторах обязательно принимают BaseFilter как один из аргументов. Неудобно конструктору GuiControl'а передавать generic тип. Использовать дизайнер форм становится сложнее.

Основной аргумент, против таких идей — не стоит вообще так заморачиваться для наших небольших проектов

А>>Просто интересно, сталкивался ли кто с таким? Может, зря я паникую

ГВ>Да нет, вроде не зря. В именах, ИМХО, путаница получается.

ГВ>Попробуйте для начала перепроектировать структуру классов, только выкиньте эти дурацкие приписки Entity — любой объект и так Entity. Получится, как минимум, Filter и Condition. Сразу вылезает интересное наблюдение: Filter включает в себя Condition и какое-то поведение по отношению к "фильтруемому" объекту. По крайней мере, с точки зрения семантики человеческого языка.

Я тоже противник приписки Entity, но поскольку моему коллеге они удобны, я не настаиваю категорически.
Re[3]: Использование "точных" названий и разделенных классов
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 03.09.08 12:27
Оценка:
Здравствуйте, a.coder, Вы писали:

AC>Имхо, следующие задачи решать станет проще:

AC>* реализация логики, связанной с фильтрами, если фильтры реализовать так, как удобно для бизнес-логики, а не для диалога.
AC>* юнит-тестирование

Хорошо, допустим.

AC>Да, в первую очередь хотелось бы ограничить интерфейс Filter GUI. Как было в примере, в 3 разных проектах используется один и тот же диалог, но из-за того, что в нем используется класс сущности для извлечения данных, неудобно эту саму сущность изменять.


Да, вполне согласен. Такое вполне может статься, особенно, если сущность подкручивалась под нужды тех или иных диалогов.

AC>Попробую описать свою проблему конкретным примером


AC>Структура проектов такая:

AC>1. PluginProject1 (enum FilterTypes1)
AC>2. PluginProject2 (enum FilterTypes2)
AC>3. PluginCoreProject3 (BaseFilter, KeywordsFilterDialog, ListFilterDialog)

AC>В PluginCoreProject3 есть классы фильтра BaseFilter и диалогов KeywordsFilterDialog, ListFilterDialog.

AC>У фильтра BaseFilter есть поле Type — типа int.

.Net-овского reflection мало оказалось?

AC>
AC>public class BaseFilter
AC>  ...

AC>  public KeywordsFilterDialog(BaseFilter filter)
AC>    ...

AC>


Странно. По идее KeywordsFilterDialog отлично знает о том, какой именно фильтр ему нужен (KeywordsFilter), но получает почему-то BaseFilter. Зачем такие сложности?

AC>Проекты PluginProject1 и PluginProject2 используют BaseFilter, но Type трактуются в каждом по-своему. Для этого заведены enum'ы FilterTypes1 и FilterTypes2. В коде же используются преобразования типа:


[skip преобразования]

AC>Такие конструкции неудобны, когда дальше в логике приходится интенсивно использовать Filter.


Ещё бы... Прости за ёрничество, а оперировать объектами нужных типов вместо базового религия не позволяет?

AC>Была идея сделать BaseFilter generic'ом, которому передавался бы свой enum в каждом проекте, но тут я уперся в диалоги.


Зачем??? Выкиньте вы этот хвост enum-ов. Не нужны они тут.

AC>Диалоги в своих конструкторах обязательно принимают BaseFilter как один из аргументов.


Ну вот и зачем? Зачем передавать в конструктор параметр базового типа, когда на самом деле нужен вполне определённый? Чтобы плодить код кастинга?

AC>Неудобно конструктору GuiControl'а передавать generic тип. Использовать дизайнер форм становится сложнее.


AC>Основной аргумент, против таких идей — не стоит вообще так заморачиваться для наших небольших проектов


Да нет, вопрос скорее в том, как обосновано решение о введении дополнительной прослойки. Если просто абстрактным "хорошо-плохо", то это одно, а если соображениями практического порядка — совсем другое. Но вам, ИМХО, имеет смысл поменять дизайн. Что-то больно много всего накручено, альтернативный способ идентификации типов через enum/int — вообще в топку (во всяком случае, из твоих примеров не следует, что это зачем-то нужно, кроме как для того, чтобы упражняться в преобразованиях BaseFilter).
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[4]: Использование "точных" названий и разделенных классов
От: Аноним  
Дата: 05.09.08 12:24
Оценка:
AC>>Структура проектов такая:
AC>>1. PluginProject1 (enum FilterTypes1)
AC>>2. PluginProject2 (enum FilterTypes2)
AC>>3. PluginCoreProject3 (BaseFilter, KeywordsFilterDialog, ListFilterDialog)

AC>>В PluginCoreProject3 есть классы фильтра BaseFilter и диалогов KeywordsFilterDialog, ListFilterDialog.

AC>>У фильтра BaseFilter есть поле Type — типа int.

ГВ>.Net-овского reflection мало оказалось?

Что-то не понимаю к чему это?

AC>>
AC>>public class BaseFilter
AC>>  ...

AC>>  public KeywordsFilterDialog(BaseFilter filter)
AC>>    ...

AC>>


ГВ>Странно. По идее KeywordsFilterDialog отлично знает о том, какой именно фильтр ему нужен (KeywordsFilter), но получает почему-то BaseFilter. Зачем такие сложности?

Есть кусок кода, который создает эти диалоги и передает им фильтр. Этот кусок кода устроен так, что он не знает конкретных типов фильтра. Возможно, Вы и правы — тут что-то с дизайном.

AC>>Такие конструкции неудобны, когда дальше в логике приходится интенсивно использовать Filter.

ГВ>Ещё бы... Прости за ёрничество, а оперировать объектами нужных типов вместо базового религия не позволяет?
Нет, религия тут ни при чем.
Тут дело в том, что у нас есть код, который просматривает коллекцию базовых фильтров. И в зависимости от типа фильтра делает какую-то работу. Как тут оперировать объектом нужного типа?
Например:
  FiltersCollection collection = ...;
  foreach (BaseFilter filter in collection)
  {
    switch ((FilterTypes)filter.Type)
    {
      case FilterTypes.FilterA:
        [...]
      case FilterTypes.FilterB:
        [...]
    }
  }



AC>>Была идея сделать BaseFilter generic'ом, которому передавался бы свой enum в каждом проекте, но тут я уперся в диалоги.

ГВ>Зачем??? Выкиньте вы этот хвост enum-ов. Не нужны они тут.
Мне нравится идея Только пока плохо себе представляю, как. Даже вопрос четко сформулировать пока не получается, что я хочу в итоге, если откажусь от enum-ов.

ГВ>Да нет, вопрос скорее в том, как обосновано решение о введении дополнительной прослойки. Если просто абстрактным "хорошо-плохо", то это одно, а если соображениями практического порядка — совсем другое. Но вам, ИМХО, имеет смысл поменять дизайн. Что-то больно много всего накручено, альтернативный способ идентификации типов через enum/int — вообще в топку (во всяком случае, из твоих примеров не следует, что это зачем-то нужно, кроме как для того, чтобы упражняться в преобразованиях BaseFilter).


Давно спорю с коллегой что тут что-то не так с дизайном. Многочисленные кастинги на самом деле раздражают, вот и думаю, как от них избавляться.
Re[5]: Использование "точных" названий и разделенных классов
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 07.09.08 22:46
Оценка: 2 (1)
Здравствуйте, Аноним, Вы писали:

AC>>>У фильтра BaseFilter есть поле Type — типа int.

ГВ>>.Net-овского reflection мало оказалось?
А>Что-то не понимаю к чему это?

Зачем дополнительно вводить Type типа int, когда у .Net полным-полно стандартных способов получить информацию о типе объекта? Больше того, по сути дела этот ваш Type — своего рода метаданные, а их вообще лучше всего заталкивать в атрибуты.

ГВ>>Странно. По идее KeywordsFilterDialog отлично знает о том, какой именно фильтр ему нужен (KeywordsFilter), но получает почему-то BaseFilter. Зачем такие сложности?

А>Есть кусок кода, который создает эти диалоги и передает им фильтр. Этот кусок кода устроен так, что он не знает конкретных типов фильтра. Возможно, Вы и правы — тут что-то с дизайном.

Значит, этот кусок кода надо переписать. Что-то тут неправильно, если из-за одного куска кода в куче других кусков кода нужно писать массу дурных инструкций.

AC>>>Такие конструкции неудобны, когда дальше в логике приходится интенсивно использовать Filter.

ГВ>>Ещё бы... Прости за ёрничество, а оперировать объектами нужных типов вместо базового религия не позволяет?
А>Нет, религия тут ни при чем.
А>Тут дело в том, что у нас есть код, который просматривает коллекцию базовых фильтров. И в зависимости от типа фильтра делает какую-то работу. Как тут оперировать объектом нужного типа?

Как правило, такой код свидетельствует об ошибках дизайна. А что будет, если добавится новый фильтр? Много таких кусков кода придётся дорабатывать? Здесь стоит подумать о том, чтобы вынести эту самую полезную работу непосредственно в фильтр. В общем, надо смотреть, что именно делают все эти куски кода и насколько часто такое встречается.

AC>>>Была идея сделать BaseFilter generic'ом, которому передавался бы свой enum в каждом проекте, но тут я уперся в диалоги.

ГВ>>Зачем??? Выкиньте вы этот хвост enum-ов. Не нужны они тут.
А>Мне нравится идея Только пока плохо себе представляю, как. Даже вопрос четко сформулировать пока не получается, что я хочу в итоге, если откажусь от enum-ов.

Скорее всего ты хочешь, чтобы можно было добавлять фильтры и диалоги фильтров, не слишком заморачиваясь доработками окружающих "кусков кода" и многочисленными кастингами.

А>Давно спорю с коллегой что тут что-то не так с дизайном. Многочисленные кастинги на самом деле раздражают, вот и думаю, как от них избавляться.


Перепроектированием. Иногда без кастингов не обойтись, но много-много чаще это означает, что попросту неправильно разложили функциональность по классам.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[6]: Использование "точных" названий и разделенных классов
От: a.coder Россия  
Дата: 08.09.08 12:37
Оценка:
[skip подробности]

А>>Давно спорю с коллегой что тут что-то не так с дизайном. Многочисленные кастинги на самом деле раздражают, вот и думаю, как от них избавляться.

ГВ>Перепроектированием. Иногда без кастингов не обойтись, но много-много чаще это означает, что попросту неправильно разложили функциональность по классам.

Спасибо. Вы подтвердили мои сомнения по поводу дизайна. Будем решать с учетом Ваших рекомендаций.
Re[7]: Использование "точных" названий и разделенных классов
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 08.09.08 20:50
Оценка:
Здравствуйте, a.coder, Вы писали:

AC>Спасибо. Вы подтвердили мои сомнения по поводу дизайна. Будем решать с учетом Ваших рекомендаций.


Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re: Использование "точных" названий и разделенных классов
От: minorlogic Украина  
Дата: 10.09.08 05:50
Оценка:
Обязательно соблюдайте согласованность названий , описанная ситуация из ряда вот неприятная.

Названия классов и переменных это целое искуство , а вот их согласованность это необходимая рутина.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Ищу работу, 3D, SLAM, computer graphics/vision.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.