Я не знаю почему, но я всегда чувствую, что я "обманываю", когда использую рефлексию - возможно, это из-за удара по производительности, который я знаю, который я беру.
Часть меня говорит, что если это часть языка, который вы используете, и он может выполнить то, что вы пытаетесь сделать, то почему бы не использовать его. Другая часть меня говорит, что должен быть способ, которым я могу сделать это, не используя рефлексию. Я думаю, может быть, это зависит от ситуации.
На какие потенциальные проблемы я должен обратить внимание при использовании рефлексии, и насколько я должен быть обеспокоен ими? Сколько усилий стоит потратить, чтобы попытаться найти более традиционное решение?
Ответы:
Нет, это не обман - это способ решения проблем в некоторых языках программирования.
Теперь это часто не самое лучшее (самое чистое, самое простое, самое простое в обслуживании) решение. Если есть лучший способ, используйте его действительно. Однако иногда нет. Или, если есть, это просто намного сложнее, включает много дублирования кода и т. Д., Что делает его невозможным (трудно поддерживать в долгосрочной перспективе).
Два примера из нашего текущего проекта (Java):
fieldX
соответствующему полю в классе и инициализировать последний. В некоторых случаях он может создать простое диалоговое окно с графическим интерфейсом на основе идентифицированных свойств на лету. Без размышлений это заняло бы сотни строк кода в нескольких приложениях. Поэтому рефлексия помогла нам быстро и без особых усилий собрать простой инструмент и позволила нам сосредоточиться на важной части (регрессионное тестирование нашего веб-приложения, анализ журналов сервера и т. Д.), А не на несущественном.Суть в том, что, как и любой мощный инструмент, можно использовать отражение, чтобы выстрелить себе в ногу. Если вы узнаете, когда и как (не) использовать его, это может принести вам элегантные и чистые решения других сложных проблем. Если вы злоупотребите этим, вы можете превратить простую в остальном проблему в сложный и безобразный беспорядок.
источник
if (propName = n) setN(propValue);
, вы можете присвоить вашим (то есть) XML-тегам то же самое, что и свойства вашего кода, и выполнить цикл над ними. Этот метод также значительно упрощает добавление свойств позже.Это не обман. Но это обычно плохая идея в рабочем коде по крайней мере по следующим причинам:
Я бы предложил ограничить использование рефлексии следующими случаями:
Во всех других случаях я бы предложил выработать подход, который избегает рефлексии. Определение интерфейса с соответствующим методом (-ами) и его реализация на множестве классов, для которых вы хотите вызвать метод (-ы), обычно достаточно для решения большинства простых случаев.
источник
Отражение - это еще одна форма метапрограммирования, и такая же действительная, как и параметры на основе типов, которые вы видите на большинстве языков в наши дни. Отражение является мощным и универсальным, а рефлексивные программы имеют высокий уровень ремонтопригодности (при правильном использовании, конечно) и в большей степени, чем чисто объектно-ориентированные или процедурные программы. Да, вы платите за производительность, но я бы с радостью пошел на более медленную программу, которая во многих или даже в большинстве случаев более удобна в обслуживании.
источник
Конечно, все зависит от того, чего вы пытаетесь достичь.
Например, я написал приложение для проверки медиа, которое использует внедрение зависимостей, чтобы определить, какой тип медиа (файлы MP3 или JPEG) проверять. Оболочке нужно было отображать сетку, содержащую соответствующую информацию для каждого типа, но она не знала, что будет отображаться. Это определено в сборке, которая читает этот тип носителя.
Поэтому мне пришлось использовать отражение, чтобы получить количество отображаемых столбцов, их типы и имена, чтобы я мог правильно настроить сетку. Это также означало, что я мог обновить внедренную библиотеку (или создать новую) без изменения какого-либо другого кода или файла конфигурации.
Единственным другим способом было бы иметь файл конфигурации, который нужно было бы обновлять, когда я переключал тип проверяемого носителя. Это привело бы к еще одной точке отказа для приложения.
источник
Reflection - отличный инструмент, если вы автор библиотеки и, следовательно, не имеете никакого влияния на входящие данные. Комбинация рефлексии и метапрограммирования может позволить вашей библиотеке беспрепятственно работать с произвольными вызывающими абонентами без необходимости проходить через циклы генерации кода и т. Д.
Тем не менее, я стараюсь препятствовать отражению в коде приложения ; на уровне приложения вы должны использовать разные метафоры - интерфейсы, абстракцию, инкапсуляцию и т. д.
источник
Отражение отлично подходит для создания инструментов для разработчиков.
Поскольку это позволяет вашей среде сборки проверять код и потенциально генерировать правильные инструменты для манипулирования / init, проверяйте код.
Как общая методика программирования, она может быть полезной, но более хрупкой, чем думает большинство людей.
Одно из реальных применений для отражения (IMO) заключается в том, что это делает написание универсальной потоковой библиотеки очень простой (до тех пор, пока описание вашего класса никогда не изменится (тогда это станет очень хрупким решением)).
источник
Использование рефлексии часто вредно в ОО-языках, если не используется с большой осведомленностью.
Я потерял счет, сколько плохих вопросов я видел на сайтах StackExchange, где
Вот являются типичными примерами.
Большая часть ОО заключается в том, что
Если в какой-либо точке вашего кода точка 2 недопустима для объекта, который вы передали, то один или несколько из них верны
Плохо квалифицированные разработчики просто не понимают этого и считают, что им можно передать что угодно в любой части своего кода и делать то, что они хотят, из (жестко запрограммированного) набора возможностей. Эти идиоты используют отражение много .
Для ОО-языков отражение должно быть необходимо только в мета-активности (загрузчики классов, внедрение зависимостей и т. Д.). В этих условиях рефлексия необходима, потому что вы предоставляете общую услугу, которая помогает манипулировать / конфигурировать код, о котором вы ничего не знаете по уважительной и законной причине. Практически в любой другой ситуации, если вы стремитесь к размышлению, вы делаете что-то не так, и вам нужно спросить себя, почему этот фрагмент кода недостаточно знает об объекте, который был ему передан.
источник
Альтернатива в тех случаях, когда область отраженных классов четко определена, заключается в использовании отражения вместе с другими метаданными для генерации кода вместо использования отражения во время выполнения. Я делаю это с помощью FreeMarker / FMPP; Есть много других инструментов на выбор. Преимущество этого заключается в том, что вы получаете «настоящий» код, который можно легко отладить и т. Д.
В зависимости от ситуации, это может помочь вам сделать код намного быстрее - или просто увеличить объем кода. Это позволяет избежать недостатков отражения:
упомянутый ранее.
Если рефлексия кажется обманом, то это может быть потому, что вы основываете ее на большом количестве догадок, в которых вы не уверены, и ваша интуиция предупреждает вас, что это рискованно. Обязательно предоставьте способ улучшить метаданные, присущие отражению, с помощью собственных метаданных, где вы сможете описать все причуды и особые случаи реальных классов, с которыми вы можете столкнуться.
источник
Это не обман, но, как и любой инструмент, его следует использовать для решения своих задач. Отражение по определению позволяет вам проверять и модифицировать код с помощью кода; если это то, что вам нужно сделать, то отражение - это инструмент для работы. Отражение - это все о метакоде: коде, который нацелен на код (в отличие от обычного кода, нацеленного на данные).
Примером правильного использования отражения являются универсальные классы интерфейса веб-службы. Типичный дизайн состоит в том, чтобы отделить реализацию протокола от функциональных возможностей полезной нагрузки. Итак, у вас есть один класс (давайте назовем его
T
), который реализует вашу полезную нагрузку, и другой, который реализует протокол (P
).T
это довольно просто: для каждого вызова, который вы хотите сделать, просто напишите один метод, который делает то, что должен делать.P
однако необходимо сопоставить вызовы веб-службы вызовам метода. Делать это отображение универсальным желательно, потому что оно избегает избыточности и делает егоP
многократно используемым. Reflection предоставляет средства для проверки классаT
во время выполнения и вызова его методов на основе строк, передаваемыхP
через протокол веб-службы, без каких-либо знаний класса во время компиляцииT
, Используя правило «код о коде», можно утверждать, что у классаP
есть код в классеT
как часть его данных.Тем не мение.
Reflection также предоставляет вам инструменты, позволяющие обойти ограничения системы типов языка - теоретически вы можете передавать все параметры как типы
object
и вызывать их методы посредством отражений. Вуаля, язык, который должен обеспечивать строгую дисциплину статической типизации, теперь ведет себя как динамически типизированный язык с поздним связыванием, только синтаксис гораздо более сложный. Каждый отдельный пример такого паттерна, который я видел до сих пор, был грязным взломом, и неизменно было бы возможным решение в системе типов языка, и оно было бы более безопасным, более элегантным и более эффективным во всех отношениях. ,Существует несколько исключений, таких как элементы управления графическим интерфейсом, которые могут быть привязаны к данным к различным не связанным типам источников данных; требовать, чтобы ваши данные реализовывали определенный интерфейс только для того, чтобы вы могли связывать данные, это нереально, и программист не должен реализовывать адаптер для каждого типа источника данных. В этом случае использование отражения для определения типа источника данных и настройка привязки данных является более полезным выбором.
источник
Одна из проблем, с которой мы столкнулись в Reflection, это когда мы добавили в смесь Obfuscation . Все классы получают новые имена, и внезапная загрузка класса или функции по имени перестает работать.
источник
Это полностью зависит. Примером чего-то, что было бы трудно сделать без размышления, является репликация ObjectListView . Он также генерирует код IL на лету.
источник
Отражение является основным методом создания систем, основанных на соглашениях. Я не удивлюсь, обнаружив, что он интенсивно используется в большинстве сред MVC. Это основной компонент в ОРМ. Скорее всего, вы уже используете компоненты, созданные с ним каждый день.
Альтернативой для такого использования является конфигурация, которая имеет свой собственный набор недостатков.
источник
Отражение может достигать вещей, которые просто невозможно сделать практически иначе.
Например, рассмотрим, как оптимизировать этот код:
В середине внутреннего цикла есть дорогой тестовый привкус, но для его извлечения требуется переписать цикл один раз для каждого оператора. Отражение позволяет нам получить производительность наравне с извлечением этого теста, не повторяя цикл десять раз (и тем самым жертвуя обслуживаемостью). Просто сгенерируйте и скомпилируйте нужный вам цикл на лету.
Я действительно сделал эту оптимизацию , хотя ситуация была немного сложнее, и результаты были потрясающими. Повышение производительности на порядок и уменьшение количества строк кода.
(Примечание. Сначала я попробовал эквивалент передачи Func вместо char, и это было немного лучше, но не почти 10-кратное отражение.)
источник
Это никоим образом не обманывает ... Скорее, он позволяет серверам приложений запускать классы, созданные пользователем с именем по их выбору, что обеспечивает гибкость для пользователя, а не обманывает его.
И если вы хотите увидеть код любого файла .class (на Java), то есть несколько бесплатных декомпиляторов!
источник