Является ли хорошей практикой использование отражения в вашей бизнес-логике? - PullRequest
10 голосов
/ 13 октября 2010

Мне нужно работать над приложением, которое состоит из двух основных частей:

  • Часть бизнес-логики с конкретными бизнес-классами (например, Книга, Библиотека, Автор, ...)
  • Общая часть, которая может отображать книги, библиотеки, ... в сетках данных, отображать их в базу данных, ...).

Обобщенная часть использует отражение для извлечения данных из бизнес-классов без необходимости написания определенной сетки данных или логики базы данных в бизнес-классах. Это прекрасно работает и позволяет нам добавлять новые бизнес-классы (например, LibraryMember) без необходимости настройки сетки данных и логики базы данных.

Однако с годами в бизнес-классы был добавлен код, который также использует рефлексию для достижения целей в бизнес-классах. Например. в случае смены автора книги наблюдатели должны сообщить самому автору, что он должен добавить эту книгу в свою коллекцию книг, написанных им (Author.Books). В этих наблюдателях пропускаются не только экземпляры, но и информация, которая напрямую получена из отражения (FieldInfo добавляется к вызову наблюдателя, чтобы вызывающий объект знал, что поле «Автор» книги изменено).

Я отчетливо вижу преимущества использования отражения в этих общих модулях (таких как сетка данных или интерфейс базы данных), но мне кажется, что использование отражения в бизнес-классах - плохая идея. В конце концов, не должно ли приложение работать без максимально возможного отражения? Или использование рефлексии - «нормальный способ работы» в 21 веке?

Является ли хорошей практикой использование рефлексии в вашей бизнес-логике?

РЕДАКТИРОВАТЬ : некоторые пояснения к замечанию Кирка:

  • Представьте, что Автор внедряет наблюдателя в Книгу.
  • Книга вызывает всех своих наблюдателей всякий раз, когда изменяется какое-либо поле Книги (например, Название, Год, # Страницы, Автор, ...). FieldInfo измененного поля передается наблюдателю.
  • Автор-наблюдатель затем использует это FieldInfo, чтобы решить, заинтересован ли он в этом изменении. В этом случае, если FieldInfo предназначен для поля Author of Book, Author-Observer обновит свой собственный вектор Books.

Ответы [ 6 ]

9 голосов
/ 13 октября 2010

Основная опасность в Reflection заключается в том, что гибкость может перерасти в неорганизованный, не поддерживаемый код, особенно если для внесения изменений используется больше младших разработчиков, которые могут не полностью понимать код Reflection или настолько очарованы им, что используют его для решить любую проблему, даже если достаточно простых инструментов.

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

6 голосов
/ 13 октября 2010

Я избегаю использования отражения. Да, это делает вашу программу более гибкой. Но эта гибкость дорого обходится: не требуется проверка имен или типов полей во время компиляции или любой другой информации, которую вы собираете с помощью отражения.

Как и многие вещи, это зависит от того, что вы делаете. Если природа вашей логики такова, что вы НИКОГДА не сравниваете имена полей (или что-то еще), найденные с постоянным значением, тогда использование отражения, вероятно, является хорошей вещью. Но если вы используете отражение для поиска имен полей, а затем просматриваете их в поисках полей с именами «Автор» и «Заголовок», вы только что создали более сложное моделирование объекта с двумя именованными полями. А что, если вы ищете «Автор», когда поле на самом деле называется «AuthorName», или вы намереваетесь найти «Автор» и случайно ввести «Автор»? Теперь у вас есть ошибки, которые не будут отображаться до времени выполнения, а не будут отмечены во время компиляции.

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

Сейчас я работаю над системой, где авторам оригинала нравились рефлексия и подобные методы. Существует множество мест, где им нужно создать экземпляр класса, и вместо того, чтобы просто сказать «новый» и класс, они создают токен, который они ищут в таблице, чтобы получить имя класса. Что это дает? Да, мы могли бы изменить таблицу, чтобы сопоставить этот токен с другим именем. И это приобретает нас ... что? Когда вы в последний раз говорили: «О, каждое место, где моя программа создает экземпляр Customer, я хочу изменить, чтобы создать экземпляр NewKindOfCustomer». Если у вас есть изменения в классе, вы изменяете класс, не создавая новый класс, а оставляя старый для ностальгии.

Чтобы решить аналогичную проблему, я регулярно создаю экраны ввода данных на лету, запрашивая у базы данных список имен полей, типов и размеров, а затем выкладывая их оттуда. Это дает мне преимущество использования одной и той же программы для всех более простых экранов ввода данных - просто передайте имя таблицы в качестве параметра - и, если поле добавлено или удалено, требуется нулевое изменение кода. Но это работает только до тех пор, пока мне все равно, какие поля. Как только у меня появятся валидации или побочные эффекты, характерные для этого экрана, система доставит больше хлопот, чем стоит, и мне лучше вернуться к более явному кодированию.

3 голосов
/ 13 октября 2010

Исходя из ваших правок, кажется, что вы используете отражение чисто в качестве механизма для идентификации полей. Это противоположно динамическому поведению, такому как поиск полей, которых следует избегать, когда это возможно (поскольку при таких поисках обычно используются строки, которые разрушают безопасность статического типа). Использование FieldInfo для предоставления идентификатора поля довольно безвредно, хотя оно предоставляет некоторые внутренние возможности (класс информации) способом, который не совсем идеален.

3 голосов
/ 13 октября 2010

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

Но я большой поклонник, если это работает, это работает.

Также, используя отражениеу вас, вероятно, есть что-то, что можно довольно легко адаптировать.

Т.е. единственное возражение, которое больше всего будет иметь, - это довольно религиозно ... и если ваша производительность нормальная, а код поддерживаемый и понятный .... кого это волнует?1007 *

Редактировать: основываясь на ваших изменениях, я бы действительно использовал интерфейсы для достижения того, что вы хотите.Если я не понимаю тебя.

2 голосов
/ 13 октября 2010

Я склонен использовать интерфейсы на своем бизнес-уровне и оставить свое отражение на уровне презентации.Это не абсолют, а скорее ориентир.

2 голосов
/ 13 октября 2010

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

Просто хорошая статья, чтобы рассказать о рефлексии -

http://www.simple -talk.com / DotNet / .net-основа / a-defense-of-reflection-in-.net /

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