{"id":41,"date":"2009-01-28T22:46:05","date_gmt":"2009-01-29T02:46:05","guid":{"rendered":"http:\/\/joemorrison.org\/blog\/?p=41"},"modified":"2009-01-28T23:20:40","modified_gmt":"2009-01-29T03:20:40","slug":"is-reflection-unhealthy","status":"publish","type":"post","link":"https:\/\/morrison.today\/blog\/2009\/01\/28\/is-reflection-unhealthy\/","title":{"rendered":"Is reflection unhealthy?"},"content":{"rendered":"<p>Am I the only one who feels a bit dirty after writing code that uses <a title=\".NET Reflection Tutorial\" href=\"http:\/\/www.codersource.net\/published\/view\/291\/reflection_in.aspx\">reflection<\/a>? Most programmers agree that strong typing is a good feature in programming languages, because it allows compilers to catch many kinds of programming errors before you run your program the first time.\u00a0 But using reflection completely bypasses that security.<br \/>\n<!--more--><br \/>\nReflection is useful for working around the type system when it gets in the way. For example say you want to write a universal object serializer. It needs to work on classes that haven&#8217;t even been defined yet, so there&#8217;s no way it can access the instance variables of those classes in a type-safe manner. Reflection provides a way to ask objects what instance variables they contain, the current values of those instance variables, and so on. There are countless applications &#8211; I don&#8217;t need to list them here. (There&#8217;s a good discussion on the <a href=\"http:\/\/discuss.fogcreek.com\/dotnetquestions\/default.asp?cmd=show&amp;ixPost=5318&amp;ixReplies=9\">Fog Creek discussion board<\/a>.) But what&#8217;s interesting is how reflection subverts strong typing.<\/p>\n<p>First, method invocations and any other operations performed using reflection are not typesafe:<br \/>\n<code><br \/>\nMethodInfo methodInfo = myObject.GetType().GetMethod(\"MyMethod\");<br \/>\nmethodInfo.Invoke(myObject, new object[] {});<br \/>\n<\/code><br \/>\nThere is no way at compile time of protecting against a type error in that code sequence. Second, most programmers won&#8217;t be able to resist checking that <code>methodInfo<\/code> is non-null, to protect against a possible null pointer exception:<br \/>\n<code><br \/>\nMethodInfo methodInfo = myObject.GetType().GetMethod(\"MyMethod\");<br \/>\nif (methodInfo != null)<br \/>\n{<br \/>\n&nbsp;&nbsp;methodInfo.Invoke(myObject, new object[] {});<br \/>\n}<br \/>\n<\/code><br \/>\nThat&#8217;s not a bad instinct. After all, who knows what kind of <em>myObject<\/em> might be passed to this code? But now we&#8217;ve subverted the type system twice. It can&#8217;t check that we&#8217;re calling the method correctly, and it can&#8217;t even check that we&#8217;re providing the right kind of object. If we provide the wrong kind of object, this code will simply do nothing, probably causing a mysterious, silent failure.<\/p>\n<p>Let&#8217;s see, what other kinds of trouble can we get into? Say we refactor the code and change the name <code>MyMethod<\/code> to something else. A smart IDE can do this automatically for us &#8211; but it will miss the reflection-based calls since they are only visible to the IDE as character strings. What will our code example do in this case? It will fail mysteriously and silently again.<\/p>\n<p>Reflection also undermines program correctness by encouraging the creation of implicit contracts. Normally if you want to create a clear contract between two classes, you create an interface. For example, if you have a strange kind of collection class which calls <em>WriteAuditRecord()<\/em> on each object that is added, you might define the collection to accept only contents of type <em>Auditable<\/em>, which would be an interface with a <em>WriteAuditRecord()<\/em> method. Anyone using the collection would get a compile-time type error if they attempted to compile code which inserts objects that do not support that method. That would lead them to read the documentation in the <em>Auditable<\/em> interface and learn about the contract between the classes. But you could also create a clever solution using reflection to check whether any inserted items support a <em>WriteAuditRecord<\/em> method, and if so call that method automatically. That would allow programmers to add items to the collection without changing their implementation to implement the <em>Auditable<\/em> interface. More flexible, right? Except that if a programmer accidentally misspells the method as <em>WriteAudiRecord<\/em>, it will not get called; another silent error that would normally have been caught by the typechecker. Or even spookier, programmers might not know about this special audit behavior and be surprised when their <em>WriteAuditRecord()<\/em> method gets called for no apparent reason.<\/p>\n<p>I&#8217;d also like to take a poke at another sacred cow: <em>attributes<\/em> (or <em>annotations<\/em> if you&#8217;re a Java person). My main beef with these is that to use them, you need to use reflection. See above.<\/p>\n<p>I&#8217;m not 100% against the use of reflection and annotations. They can be very useful when creating frameworks that need to work on any kind of object (e.g. for serialization and persistence, or for configuration systems like Spring) but my point is they should be used sparingly and you should take a shower afterward.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Am I the only one who feels a bit dirty after writing code that uses reflection? Most programmers agree that strong typing is a good feature in programming languages, because it allows compilers to catch many kinds of programming errors before you run your program the first time.\u00a0 But using reflection completely bypasses that security.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,8],"tags":[22,23,21],"class_list":["post-41","post","type-post","status-publish","format-standard","hentry","category-architecture","category-general-development","tag-annotations","tag-attributes","tag-reflection"],"blocksy_meta":"","_links":{"self":[{"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/posts\/41","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/comments?post=41"}],"version-history":[{"count":9,"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/posts\/41\/revisions"}],"predecessor-version":[{"id":49,"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/posts\/41\/revisions\/49"}],"wp:attachment":[{"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/media?parent=41"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/categories?post=41"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/tags?post=41"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}