正在使用reflectiondevise的气味?
我看到很多C#,.net问题在这里使用reflection解决。 对我来说,他们中的很多人看起来像以良好devise(OOP)为代价来弯曲规则。 许多解决scheme看起来难以维持和“脚本化”。
一般来说使用reflection是一种好的做法吗? 有什么东西只能通过反思来解决吗?
编辑:
请举例说明反思是唯一的好方法。
例子:
- 通过configurationdynamic加载types
- 使用“约定”风格注册(注册组件与你的容器实现一个接口或有一定的命名约定)
- 检查/使用自定义属性/types元数据
reflection是一种工具,就像“扔”一样。 你应该到处扔吗? 没有! 那么这是一个代码气味使用扔吗?
对我来说,他们中的很多人看起来像以良好devise(OOP)为代价来弯曲规则。 许多解决scheme看起来难以维持和“脚本化”。
老实说,“好devise”与OOP没有多大关系。 我认为一个更大的devise气味是值得关注的是,好的devise完全等于面向对象的信念。 如果没有面向对象程序devise,我们就不能有好的devise,而且如果没有devise好,我们就不能遵循面向对象程序devise的规则。 这几乎和人们对“气味”的痴迷一样糟糕。 程序员应该用他们的大脑,而不是他们的鼻子。
一般来说使用reflection是一种好的做法吗? 有什么东西只能通过反思来解决吗?
我看到它的方式,反思主要是语言缺点的一个症状。 理想情况下,一种语言应该允许你做你想做的事情,而不用通过反思来“弯曲规则”。 但是大多数不会,而C#肯定不会,所以反思偶尔是你唯一明智的select。
reflection有很多“正确的”用法。 dynamic加载types/库将是一个明显的。 或者检查属性。 大多数unit testing框架也依赖于reflection,这很好,因为它们必须有一点侵入性,以便易于使用并获得我们希望testing的代码。
但是大多数执行某种types检查的用户代码,在运行时testing一个types是实现某个接口还是具有某个成员函数,这是一个理想语言中不应该有必要的东西的标志。
如果你想认为它是一种气味,把它称为一种语言的气味,而不是devise。 (当然,它也可以在devise中被过度使用,但是在我经常遇到它的地方,这是必要的,因为语言缺乏performance力)
反思有时是做某些事情的唯一途径。 这是一个非常强大的工具,有时候可以被那些知道反思的人过度使用,但也许不是别的。 当别的东西能更好地工作时,过度使用reflection可能是一种devise气味,但更多的时候可能只是不好的编码。
曾经有一个处理文件的程序(这个描述如何通用)
通过使用reflection,所有你需要做的就是把一个DLL放到一个文件夹中,应用程序会select它并使用reflection来寻找实现了特定接口的类并检查一些属性。 不需要configuration文件。 只要放下就行,这对于生产系统来说非常方便,因为我们不需要任何停机时间。
与大多数解决scheme一样 还有其他一些方法可以达到同样的目的,但是反思确实使得这很容易。
我不会说使用reflection是一种devise气味。 这是一个非常有用的function,使得静态语言更具dynamic性。 现在从实际的angular度来看,如果没有它我能解决我的问题,我会尽量避免反思。
在我看来,反思应该是最后的手段。 由于语言的语义可以以非常奇怪的方式改变,所以reflection使得代码真的难以理解。
我会认为这是一种气味。 也许不是坏习惯,但是会引起一阵眉毛。
从概念上讲,reflection是一个强大的工具,可以用作从非代码到代码的网关以及多态工具 。
例如…
- 取一个types的string表示并把它变成一个对象。
- 不是硬编码框架或插件在一起。
- dynamic地使用来自不同程序集的对象而不知道它们是什么。
- 无需编写专用代码就可以对数据进行序列化。
正确使用它是一个巧妙的工具,可以将代码提升到可重用性和灵活性的下一个级别。 没有错。
devise气味唯一的时候就是它被用来做一些传统的function已经覆盖的东西。 (也就是说,你不想使用Reflection来获取DataRow的值)。
用大的力量来承担很大的责任,反思是一个非常强大的工具,使用得当非常好,使用不当时很糟糕,诀窍是要知道什么时候用过
和其他任何技术一样,如果你过多地关注它,你可能会开始将它应用到错误的问题上。
然而,有些事情根本不可能没有反思。 任何一种通用的序列化都是一个很好的例子。 另一个是任何一种插件框架,在编译时都不能访问它在运行时可能需要使用的所有类。
有一些问题只能用反思才能解决,但是我认为,只要有可能,就可以,也许应该避免。 C#是一个静态和types安全的语言,所以使用这个优点。 我想,使用reflection往往是相当容易出错的。
像所有事情的答案是“这取决于”
reflection的有效使用是在框架中,例如一个插件框架可能会使用属性声明插件类,testing和嘲笑框架是另一个例子。
但我同意,一般来说,在一个业务应用程序的行,大部分时间,这将是一个“代码味道”(并不总是……)
reflection使您可以在运行时检查编译器在编译时使用的相同信息。 因此,任何你可以用reflection做的事情都可以在编译过程中没有任何反映。 这并不意味着reflection没有用处:你可能不知道你要问什么问题,直到运行时。
如果您在编译时知道某些东西,请在types系统中表示。 这会让你在编译时发现错误。 例如,
string propVal = myObj.SomeProperty;
这里我们说我们知道在编译时myObj
有一个名为SomeProperty
的属性,它是一个可赋值给string
的types – 事实上,虽然在这里是不可见的,但我们还必须指定一个类或myObj
接口types。
string propVal = (string)myObj.GetType() .GetProperty("SomeProperty") .GetValue(myObj, null);
在这里,我们说myObj
可能有相同的属性 – 或者它可能不会(在这种情况下,我们会在运行时得到一个exception)。
第二个,使用reflection,看起来but </s>,但在C#4.0中,它看起来几乎相同。 它通常被认为比较慢,但是这取决于上下文,并且可能不太适用于C#4.0中的dynamic特性。
但真正的区别仍然是:静态types的版本帮助我们在编译期间发现错误,而不是延迟这个发现直到运行时。
所以如果你想充分利用静态types系统来捕捉编译过程中的错误,那么试着通过types系统来陈述你的假设,这相当于说:避免reflection,除非真的有必要。
编程是关于构build抽象的。 reflection是构build抽象的一个非常强大的工具。 所以,不,如果它导致更less的代码更容易理解,我不会说这是一个devise的气味。
你们中的一些人已经指出,reflection在框架,testing,嘲笑等方面有一席之地。如何在业务线应用程序?
根据我的经验,当您编写某种规模的业务线应用程序时,您不可避免地最终会编写自己的领域特定框架和库。 这就是思考的地方。
不,reflection不是一种devise的气味。 可以说,它可以被称为“语言/平台气味”。
因为代码和代码元数据都存储在程序集中,所以使用了reflection。 因此,他们总是更新和同步。 您可以编写关于元数据的常规约定,而不是在常见情况下明确。
在.NET中模块化,模块自我描述是一个很大的好处。
这可能是由于我自己作为程序员的个人发展,但是我发现学习反思主张对交付成果(程序集)非常需要注意。 当然还有TDD。
reflection的一个很好的用法是当你想实现一个附加体系结构。 你需要一些方法来指定“这里是一个DLL,加载它并尝试实例化一个types”。 你不知道这种types, 所有你知道的是,有一些你可以访问的接口。 唯一的办法就是反思。
我们的应用程序有大量的模块,你可以在里面运行。 我们没有对select模块时需要启动的类的列表进行硬编码,而是有一个数据表,其中列出了模块DLL的名称以及从中运行的类。 这样,当我们需要添加一个新的模块时,我们只需要在表中添加一个新条目。 启动模块的代码不会改变。
我正在使用一个项目(这是我第一次)反思。 我不得不承认,这看起来不太好。 通常我会争取非常小的评论,相信代码应该尽可能地自我评论,但是在这个项目中,我增加了频繁的评论; 这既是为了解释下一个可能需要维护代码的开发人员正在发生的事情,还是为了我自己的利益而“大声思考”。
底线:如果看起来不明显,请添加评论。 总是想想你后面的人谁可能不得不处理你的烂摊子。 反思可以看起来很乱,所以相应的评论。
那么,清晰的reflectionAPI在那里,因为它们满足了需求,而且有一些问题只能用reflection来解决。 基本上,当需要根据只在运行时可用的types信息而不是在编译时才能做出决定的时候,需要进行reflection。
有时它实际上提高了代码的可重用性。 作为一个特例,我曾经写过一个将csv导入数据库的程序。 使用ORM为这些表创build类,然后反思这些,我可以创build一个导入程序,只有特殊情况需要注意,添加一列除了将其添加到数据库表之外可能不需要其他任何东西,知道它存在于文件中。
但正如其他人所说,这主要是一个正确使用的问题。
没有它大量使用networking框架本身的反思,因此赢得了广泛的欢迎
使用F#大量使用reflection
所有的reflection都是让你在运行时观察types。 如果你是黑客,我想你可能会编写一些Rube Goldberg的东西,但同样可以说很多其他的技术。
框架的许多核心function,如属性,根本无法反映。
这是最臭的气味之一。 一种“完全封闭”的语言不需要反思。
任何人都可以看到使用reflection的好处,我认为reflection可以帮助你实现更好的devise,特别是OOPdevise概念,而不需要编写更多的代码。
例如,您可以构build依赖于抽象的松散耦合的图层,并使用reflection来控制运行时特定于实例的行为。
最明显的是:概括的UI层/组件。
ASP.Net MVC和dynamic数据的灵活性和生产力只是一个例子,你也可以看到GridView。