Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is reflection in the server?

2025-01-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)05/31 Report--

This article mainly introduces "what is reflection in the server". In daily operation, I believe many people have doubts about what reflection is in the server. Xiaobian consulted all kinds of information and sorted out simple and easy operation methods. I hope to help you answer the question of "what is reflection in the server"! Next, please follow the small series to learn together!

Common Software Framework Challenges

Suppose we want to develop a generic software framework that allows users to customize callback functions (methods) for a wide variety of scenarios to implement rich business logic functions, such as a game script engine. One way to do this is to use the observer pattern to drive the entire framework in an event-driven manner. Users organize and implement business logic by defining response functions for each event. The framework also provides access to custom events and their response functions. In some implementations, we might find a lot of code that "registers events" or distributes calls to event functions using a giant switch…case…. For example, we want to do a server-side basic process framework, this framework allows users to fill in a few callback functions, can become a stable and persistent background service process. One part of this is that you need to define program launch events so that users can customize what the program launches to do. Then we can define a string of "Init" to represent this event, and record "Init" pfunInit() in the callback hash table of an event response function. Alternatively, a constant macro INIT=12 is used to represent this event. At the main loop of the program, switch…case…is used to check the type code representing each event. If it is found to be equal to the INIT macro, the code below case INIT is called (usually a separate function, such as pfunINit()).

Maintaining long "register event" codes and long switch... case... are equally lethargic and error-prone. This code often comes with a lot of "constants," because the data used as the key of the callback function is often some custom constants. The simultaneous maintenance of these constants is also often exhausting. These long lists of code often need to be used by multiple developers, so it's easy to have problems like you changing mine wrong and I overwriting yours. These problems are very "low-level," but they are not easy to find.

[Key control code for game/JS]

Does our framework code have to be filled with long string constants, or integer constants? The answer is no, because many programming languages provide reflective functionality. In compiled languages such as C/C++, code generation techniques can also be used to simulate reflection-like capabilities.

What is reflection?

To see what reflection is, let's look at an example of an observer pattern. Suppose we are writing a GUI program that places a button on a form called "ButtonA" and expects a function we wrote to be called when the button is pressed. According to the design of the observer pattern, when this button is pressed by the user, the program bottom layer should be able to detect this event, and then generate an "event" within the process. This "event" object often carries this information: the name of the button pressed. If we code it the way we used to register events, we have to register a callback function to the observer object before the button is pressed, say at program initialization: RegisterEvent("ButtonA", ONCLICK, myOnClick) -- ButtonA pressed event-myOnClick(). The function myOnClick() here is the response function we want to handle when ButtonA is pressed. However, we can solve this problem in a more convenient way: we change the name of myOnClick() function to ButtonA_OnClick(), and then the observer automatically looks for a function named ButtonA_OnClick after the event "ButtonA" is pressed, and calls this function if he finds it. -- Obviously, this approach does not require manual registration of callback functions in advance, but simply decides what function to call according to the convention of function name. Generally speaking, we think that these function names, class names, and attribute names do not play any important role in the process of running the program, so that we will use some "obfuscator" software to process the source code and mess up these custom names without affecting the operation of the program. However, if we use reflection techniques, programs can retrieve and retrieve entities in source code corresponding to function, class, and attribute names in real-time using constants, and can also call these things.

[Spring configures object relationships via XML]

From a code maintenance point of view, it is risky that the names of classes, members, and methods are managed and known by some "configuration file" outside the program. Because we often don't think of configuration files as important as source code, errors and omissions are not assisted by compilers or IDEs, so some bugs that are difficult to debug often arise from these locations. However, it is widely welcomed as a technology that saves a lot of framework code. The problems mentioned above are now gradually solved by another technology,"metadata"(or annotations, characteristics), which combines configuration files with source code, which can greatly improve the above problems.

Reflective communication function

When we write programs for communication functions, the traditional idea is to define protocols, that is, to define protocol headers, protocol packet lengths, protocol packet fields, and so on. In a more complex network service program, there are easily dozens or hundreds of such protocols. It's actually not easy for programmers who maintain code to figure out how to make sense of so many protocols defined by others. It's easy to think of an object model instead of a communication protocol definition. The answer is yes. However, there is a new problem with using the object model: an object is a memory structure at runtime. How can the data in the object be received and sent over the network? The easiest way to do this is to use memcpy(), Linux provides this powerful API that can turn any data in memory into an array of bytes, and then we can send it directly over the network. However, if our object is not a simple struct (and simple structs are problematic), but an object in which there may be pointer members, such a copy is impossible to take into account the data pointed to by those pointers. Moreover, if the programs at both ends of the transceiver are not of the same language (operating system, platform), such memory structure data may be meaningless, such as copying a C++ object memory directly to a JAVA program, which must not be used directly. So, if we want to define communication protocols in terms of object structures, we need a way to convert objects into generic byte arrays, which is the ability to "serialize/deserialize." I'm not going to say much about serialization here, except that when these objects are serialized, they can be used as carriers for communicating data. The question is, if we receive a piece of object-serialized data, how do we construct an object for that data? The answer is to use reflection, which takes the name of an object class from the data, constructs an object from that name, and then takes the data of the remaining members from the data and copies them to that object one by one. From this point of view, as long as we have the reflection function, we can let the user simply construct an object, and then send the object to the other end of the network, and the other party can also receive an object directly, so that when writing the communication program, as long as the object is defined according to the business requirements. For programmers who read code, there is no need to install a string called "encoding and decoding" in their minds, as long as the definition of "brainless" and the processing object can be.

A common design pattern in communication programs is the command pattern, which is derived from traditional network processing based on command words: parse out command words and invoke corresponding processing functions through switch... case. Communication programs in command mode are often very simple, that is, to define a type, the member attributes (communication protocol) of this type can be defined at will, as long as a Process() method is set-the content of this method is to receive this type of object, how to deal with the container. Since reflection allows us to reconstruct this object in another part of the network, we can also call this predefined Process() method, which is defined together with the protocol object class, so it knows all the member definitions, so that this processing method does not have to struggle to get the specific data content through forced type conversion as in previous programs. Reflection is a crucial part of the command-mode communication program implementation, because when we receive a packet, we must get the class name of the object corresponding to it from the packet and then create the object corresponding to this class. Once the object is created, we can call its deserialization function to match the contents of the object to the data package, and finally call its Process() method, and we're done. This design allows you to define class objects of the same structure in different languages for communicating between programs on different language platforms without defining complex protocol definitions. Some powerful object data tools, such as Google Protocol Buffer and Apache Thrift, can directly use a common IDL language to generate class definition source code in various languages, which is more convenient.

[Set ADO database control properties with interface on delphi]

JavaBean is a well-known "object convention" used by reflection in JAVA: as long as you write JAVA types whose members are similar to setXXX() or getXXX(), many frameworks will automatically recognize and process these member functions to achieve functions such as automatically updating member data and automatically associating interface content. Another similar example is JMX, the JAVA common monitoring standard interface, you can define the class object resolution, member attribute values can be changed into statistical lines, modifiable table items, methods into buttons. In the field of game development, reflection is also widely used for the purpose of combining graphic art resources and program code: for example, Flash Builder can bind a Flash animation object to a MovieClip type through reflection, thus obtaining an object that has both art effects and user-defined behavior. After Unity3D binds 3D game objects and script components, the Start()/Update() function calls in the script are also made through reflection, so that developers do not have to bind the script type to a certain base class, and the functions called by reflection can still have different return values (different function prototypes), thus realizing coroutine or non-coroutine calls.

[Specify the associated custom class for an animation in flash editor]

Reflection can extract information from the source code and combine it with other data to greatly improve the ability of the source code, so it has a very important position in terms of development tools. We no longer need to write code and connect the data of the source code with the external structure over and over again, but simply develop a reflection capability framework, which allows us to implement some kind of "convention" of the source code, so as to realize various kinds of rapid development capabilities.

The best partner for reflection: metadata

In the process of using reflection, we often find that there are still some problems with the source code directly as data. For example, our source code may be modified for some non-business factors. Renaming and changing parameter types are very common when refactoring. So we often still can't leave the configuration file, write the name in the source code into the configuration, and then the framework runs according to the configuration. A typical example is Hibernate, a well-known ORM framework that allows you to associate source code types with database and table structures. Logically speaking, using reflection, we can directly create objects with the same names as database tables and fields, and we can directly associate them, but if our source code needs to modify these names and then change the contents of the database, it will be too troublesome. So we have to write a lot of configuration files to associate what tables correspond to what classes, what fields correspond to which attributes…These configuration files are often as many as the number of tables using the database, and any modifications must remember the modifications corresponding to these configurations. We are forced to maintain three things at the same time: database structure, configuration files, and source code. However, if our platform supports "metadata," the problem is solved easily. Because we can write configuration file projects directly inside the source code. We use comments like this before the class name of the source code to indicate which table of the database this class corresponds to; comments before the attribute name to indicate the corresponding field, default value, and so on. So we only need to maintain two things: the database structure and the source code. This greatly reduces the complexity of the project.

One of the first and most famous metadata I came across was JavaDoc technology for synchronously modifying API documentation, which made updating documentation less of a chore. Because documentation can be written in comments on source code, it is possible to update documentation as you modify code. More importantly, javadoc tags automatically map the "name list" and related comments in the source code. It should be known that this mapping can take considerable effort if it is done manually. Under javadoc education, I feel very close to java annotations and C#attributes. Previously, those configurations that required a large number of class names and method names could be recorded directly in the source code. And some client code associated with art resources can also be connected to the correct graphics resources through special tags in the source code.

An important technique that enables the "metadata" in this source code to take effect is reflection. Since our metadata handlers generally need to correspond to class and method names in the source code, we must use reflective methods. This reflection, in turn, provides a powerful mechanism for us to arbitrarily add "metadata."

Reflective Changes in Software Development

We used to believe that data structure + algorithm = program. But from today's software industry, although there are still a lot of software dedicated to computing being developed, we are exposed to more software, all of which are so-called "information management system" software. This kind of software is not to deal with complex computing tasks, but to a variety of real-world information, add, delete and change is the most popular description of these information processing. When we deal with this information, if we still regard the carrier source code of the program as an indispensable link in the compilation process, then we must deal with a large number of additional data forms: databases, configuration files, IDE configurations... However, under the trend of object-oriented, the source code can be regarded as a "tree-like" data carrier. Object-oriented definition of classes, members, methods, is a real-world entity image, they contain structures and constants, often directly become the source of data in the system. In MUD word games, almost the entire game world is written in the form of source code constants, which not only does not become a maintenance problem, but also makes the development of the whole game easier, because programmers are most accustomed to working with source code.

Reflection is a feature that makes all the data in the source code, including the "name symbol table," available to the developer, making the software development process from a pure algorithm implementation process to a comprehensive information management process. This may seem unprofessional, but in an age when programming is no longer "high-tech," this technology can help a large number of developers write source code in a "conventional" way, thus automatically gaining strong support from frameworks. Creating frameworks that allow the "conventional" way to run source code is a feature that new frameworks should have, because human creative time should not be wasted on a lot of repetitive and similar work.

At this point, the study of "what is reflection in the server" is over, hoping to solve everyone's doubts. Theory and practice can better match to help everyone learn, go and try it! If you want to continue learning more relevant knowledge, please continue to pay attention to the website, Xiaobian will continue to strive to bring more practical articles for everyone!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report