Здравствуйте, undo75, Вы писали:
U>а нафиг это все, ели по большому счету нужно джейсоны туда сюда гонять, да запросы в базу писать? упрощенно если.
Допустим, однако то, что в конкретно твоей кейсе рефлекшн ненужно, не означает, что ненужно вообще, в целом.
Ну не хтели предыдущие поколения следовать kiss штош теперь, весь рабочий код на свалку?
Выходит в твоем случае иллюзорно избыточно гибкая архитектура трансформируется в неиллюзорный технический долг по чистке вот этого всего, судя по твоей истории.
Здравствуйте, undo75, Вы писали:
U>дак просто есть куча других путей для решения задач. зачем усложнять все? причем вообще все.
Без конкретики — ничего не ясно. вы даже не ответили, с чем именно проблема, с рефлексией или с кодогенерацией.
Усложнять можно вообще везде где угодно, с любым подходом. У каждого инструмента есть границы применимости.
Если вы инструментами не владеете, то подозреваю, проделываете раз в 100 больше лишней работы.
Это все ровно ничего не говорит о том, что так или не так с вашим проектом
И у рефлексии, и у кодогенерации есть бенефиты — сокращают количество рукописного кода в десятки раз.
Если у вас на проекте чтото не так пошло, варианты
1. вы не умеете этим пользоваться — с ваших слов, у вас нет опыта
2. товарищ, который писал, не умел этим пользоваться — ваше предположение
3. цели, масштабы проекта изменились
Здравствуйте, undo75, Вы писали:
W>>А как же вот это вот все: побегать по названиям пропертей / методов объектов (например ваял как-то тестраннер, который по содержимому импортов в сборках определял, в каком конкретно тестфреймворке запускать тестики), сгенерить-запулить "на лету" какой-нить код в виде пользовательского скрипта? и еще 1001 применение?
U>а нафиг это все, ели по большому счету нужно джейсоны туда сюда гонять, да запросы в базу писать? упрощенно если.
Потому и нужно. Например, если у вас хрен-знает-сколькилион таких методов, с тз разработки проще сделать это именно через метапрограммирование
Вместо выписывания тысяч методов, и тестирования! вам нужен один конфиг/дсл/скрипт/итд.
можно пойти иначе — выписывать все по кусочку. Только вот стоимость разработки и поддержки на мой взгляд ну не очень.
Единственное, на что можно сетовать — кодогенерация это интрузивная вещь, избавиться от неё довольно трудно, в отличие от обычного дублирующегося кода.
Здравствуйте, undo75, Вы писали:
U>для прикладника он вообще нужен?
Для прикладника — нет, не нужен.
Задачи рефлекшна — подготовка DSL.
Как раз для того, чтобы прикладник писал поменьше.
Все сценарии, описанные в топике — это как раз именно такие примеры.
В языках "без рефлекшна" прикладник вынужден объяснять платформе, что делать с его типом данных, императивным кодом*:
class CMyObject : public CObject
{
public:
int x, y;
void Serialize(CArchive &ar)
{
CObject::Serialize(ar);
if (ar.IsStoring())
ar << x;
else
ar >> x;
}
}
В языках "с рефлекшном" платформа в состоянии самостоятельно выяснить, из чего состоит СMyObject и сериализовать его, или сгенерировать для него форму редактирования, или сохранить его в реляционную СУБД, или построить для него операторы == и !==. Прикладнику об этом задумываться противопоказано. Ему важно знать, каким атрибутом отключить сериализацию CMyObject::y; а как именно это работает — то ли рефлекшном, то ли компайл-тайм магией — дело десятое. Если прикладник вынужден об этом думать — значит, реализация неудачная. Прикладнику надо
[Serializable]
public class MyObject {
... никакого boilerplate про сериализацию - только прикладная логика, уникальная для этого класса.
}
* пример умозрительный, иллюстративный. Я знаю, что конкретно на этом языке можно решить эту задачу и без рефлекшна, и без прямой императивщины в прикладном коде.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
SP>>ну и когда добавится новое поле (н-р Surname) придётся менять все методы. Бред. Точнее в С++ как-то так и едят этот кактус, но это явно не то, к чему надо стремиться
U>а как и где это обходится?
Если известно, что класс описывает "плоские" объекты, в которых свойства соответствуют хранимым атрибутам (а не рантайм-состоянию со сложной эволюцией), то его можно сконструировать гораздо компактнее:
public record Person(string FirstName, string LastName);
Это приведёт не только к объявлению свойств FirstName и LastName и публичного конструктора с одноименными аргументами, но и к автоматическому порождению метода Equals, который будет устроен примерно так, как вы показывали.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Wolverrum, Вы писали: W>Свой, более лутшый Спринг и Энтити наваять
Это уже не прикладник. Это платформист.
Платформисту рефлексия — лучший друг, товарищ и брат. Также, как шаблоны, перегрузки операторов и функций, функции высшего порядка, и прочие сантехнические инструменты.
А прикладник — он кнопку нажал, говно смылось. Всё.
P.S. Один мой коллега построил себе дом, завёл систему умного дома. Смеялся над типичными внедряльщиками таких систем. "Они спрашивают: сколько у вас будет сценариев освещения?"
Ему очевидно, что основных "сценариев" для любого освещения всего два: "сделай поярче" и "сделай потемнее". А вот эти все "просмотр кино"/"видеозвонок другу"/"семейный ужин от 2х до 4х человек" — наркомания, которой невозможно пользоваться. Точно так же, как приборной панелью с 38 кнопками типа "нижняя подсветка в винном шкафу" и "софиты юго-запад".
Всё, что мы пилим — это способы борьбы со сложностью. Все несущественные подробности нужно убирать с глаз долой.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, undo75, Вы писали: U>а нафиг это все, ели по большому счету нужно джейсоны туда сюда гонять, да запросы в базу писать? упрощенно если.
Ну так это и есть каноническая область применения рефлекшна. Любая сериализация/десериализация джейсона в строгий тип требует информации о том, как свойства класса раскладываются на атрибуты и коллекции.
Если нет строгого типа — то нужно полное покрытие тестами, иначе любое мелкое изменение в API приводит к отложенным 500 Internal Error: null reference exception.
А для запросов в базу безусловный непревзойдённый лидер — это https://github.com/linq2db/linq2db. А там под капотом — сплошной рефлекшн, причём не только на чтение, но и на запись (с порождением кода в рантайме).
Но, повторюсь, прикладнику всё это напрямую не видно. У него в коде вообще не должно быть строки вида using System.Reflection.
Просто работает магия вида
var q =
from p in DB.Products
where p.Category == category
orderby p.Rating descending
select p;
if (maxPrice.HasValue)
q = from p in q where p.Price <= maxPrice.Value;
var d = q.ToList();
return JsonSerializer.Serialize(new {Count = q.Count; Items = d});
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, undo75, Вы писали:
U>для прикладника он вообще нужен? ни одной задачи с потолка не смог придумать. U>не ну я понимаю, орм там всякие. для прикладника нафига? U>в своей практике применял, только когда изучал
U>п.с. навеяно текущим местом работы, где на нем вообще все ) из-за этого отладка сильно затруднена.... ничего сложного, но все через жопу делается и занимает кучу времени. имхо выбор был мягко говоря не обоснован. видимо на истоках был юноша со взглядом горящим, который про это прочитал и его кто-то послушал. и панеслась... других предположений у меня нет
U>в моей практике потребовалось лишь один раз. U>была библиотека и требовалось дернуть закрытый метод. без него ну вообще никак. исходников не было. и все. за 20 лет практики..
Использовал один раз для написания своей библиотеки для доступа к бд. В принципе рефлексия для подобных простых, рутинных операций и где нужно отобразить одно в другое или соединить как-то одно с другим. Основной недостаток ее это то, что тип является частью контракта, например у нас может быть функция использующая рефлексию для которой нужно что бы все свойства входного объекта были публичными. В коде это ни где не прописывается, мы не можем описать некий метакласс классы которого имеют только публичные свойства и потому надежды на компилятор нет.