قالب وردپرس درنا توس
Home / Tips and Tricks / What is “reflection” in programming? – CloudSavvy IT

What is “reflection” in programming? – CloudSavvy IT



programming illustration
Shutterstock/whiteMocca

Reflective programming is a mechanism that allows a process to have introspective capabilities. Reflection APIs built into programming languages ​​allow you to inspect code at runtime. You can use this opportunity to learn more about the surrounding codebase and its contents.

Reflection is often discussed in the context of object-oriented programming. You often use reflection to discover codebase entities at runtime. The language̵

7;s reflection API allows you to inspect classes, methods, properties, and types from within your system. It allows you to build more dynamic functionality.

Systems that use reflection are able to question and adapt their own environment. This is where reflection differs from ordinary value introspection. A language with full support for reflection makes it possible to modify the codebase at runtime, essentially allowing the source to rewrite aspects of itself.

An example of reflection

A common use for reflection is during testing. Reflection can help you spot the lessons by exposing their internal behaviors. A class method that is protected or private would usually not be testable; by using reflection you can override the visibility constraint so that it becomes public in your unit tests.

class Test {
 
    protected int $Value;
 
    public function __construct(int $Value) {
        $this -> Value = $Value;
    }
 
    protected function computeValue() : int {
        return ($this -> Value * 2);
    }
 
}
 
/**
 * Without Reflection
 */
 
$t = new Test(10);
 
// Error - the method isn't publicly accessible
assert($t -> computeValue() === 20);
 
/**
 * Using Reflection
 */
 
$reflectionMethod = new ReflectionMethod(Test::CLASS, "computeValue");
$reflectionMethod -> setAccessible(true);
 
$t = new Test(10);
 
// This now works!
assert($reflectionMethod -> invoke($t) === 20);

In this example with PHP, the Test class defines a protected method used internally. Since the method performs a calculation, you may want to test it in units. You can’t call the method externally, but PHP’s Reflection API allows you to get around the visibility restrictions. A ReflectionMethod instance provides information about the method and lets you call a modified version.

While this is helpful, be aware that it can be abused. Widespread use of reflection in testing is often an indication of bigger problems in your codebase. It implies that the interface of the class is too restrictive and not suited to its responsibilities. In many cases it is better to refactor the protected method into a new class that exposes its own public interface.

This is what it might look like for the example above:

class Calculator {
 
    public function computeValue() : int {
        return ($this -> Value * 2);
    }
 
}
 
class Test {
 
    protected int $Value;
 
    protected Calculator $Calculator;
 
    public function __construct(int $Value, Calculator $Calculator) {
        $this -> Value = $Value;
        $this -> Calculator = $Calculator;
    }
 
}

The calculator component is now its own standalone unit with a testable public interface. This goes hand in hand with dependency injection – the Test class is now given a Calculator which implements the calculation logic.

Using Reflection With Unpredictable Values

Reflection is also useful when writing generic code within a framework. You may need to interact with user-supplied types that you cannot foresee. Reflection can help if you don’t know which methods and properties a type reveals.

You can get a sense of the functionality of the type without any prior knowledge of the source. This is useful in the context of logging and error reporting components that may want to dump the member list of any class they were passed to.

Data marshalling systems are also often implemented in this way. Imagine a marshaller taking a class and converting it into a JSON representation. You could define a convention that precedes each method with get and ends with Json (e.g getUserJson()) must be called by the marshaller and added to the output. Reflection provides the mechanism to get the list of methods. You would then implement logic to identify the ones you should call.

Reflection, compilation and editing en

Reflection provides additional capabilities in compiled languages ​​that use linked libraries and assemblies. Reflection APIs allow you to inspect the contents of loaded assemblies. In languages ​​such as C#, you can dynamically load additional assemblies by using Reflection APIs.

This approach can be useful if you are implementing a plug-in system with user-supplied assemblies. Your program does not know which plugins are available when it is compiled. Every time it launches, it has to check the file system to find available plugin assemblies. Once a plugin is found, Reflection provides a mechanism to load and instantiate its members.

You can inspect the plugin, find the classes it provides and register it with your application. Further inspection of the assembly may yield the plugin name and version for display in your logs and user interface.

Reflection can also be used to disable assemblies based on external configuration. Let’s say you write an application that stores image files in storage. You may have a LocalStorageDriver, FtpStorageDriver and AmazonS3StorageDriver, each in his own assembly (a .dll in C#).

By using reflection, you could provide a “storage driver” key in your system’s configuration file. The appropriate assembly is dynamically loaded based on the value of your configuration file. You would inspect the assembly to discover the class that your . implements StorageDriver couple.

This approach allows you to disable parts of your system at runtime. You don’t need to recompile or restart your program to switch assemblies. This gives you more flexibility and helps implement configuration guidelines.

Eval Statements

Reflection is closely related to eval. Many programming languages ​​provide a way to output dynamic string values ​​as source code.

Eval is a permutation of reflection with an almost limitless power. It allows you to create and run new code within a live program. This poses a potentially catastrophic security issue if user input is entered into the eval wire.

An eval statement should be used when there are no other options. You must ensure that the statement is executed in a restricted context that cannot be exploited by users. Remember that a successful code injection would give an attacker the same privileges as your normal application code.

Conclusion

Reflection is a programming technique that gives code introspective skills. Effective use of reflection allows you to write more dynamic systems and take advantage of more automation. You can also use reflection to test the otherwise unreachable private code.

You have to be careful. Reflection APIs in programming languages ​​are powerful, so with them comes responsibility. The biggest problem is Reflection’s ability to undermine the protections of your programming language.

Reflection enables the existence of scenarios that would otherwise be impossible, such as writing to “immutable” variables and widespread public use of private methods. You must be confident that your code respects the rules of the language. The use of the reflection APIs should therefore be carefully considered and tailored to specific sections of your system.


Source link