• Nenhum resultado encontrado

Coupling propagation: passing Managed objects

Part III: Robusta

6.2 Decoupling component instances

6.2.7 Coupling propagation: passing Managed objects

Handling managed objects requires not only releasing the objects when indicated by the framework that the creator component is no longer valid, but also paying attention to avoid propagating the object reference. Propagation is the receiving of an object and then passing it on to another component. Free objects do not have any particular conditions put on propagation, as by definition, they may be freely shared among components. However, managed objects must be properly released when the creator component is invalidated, otherwise, this may result in a memory leak or other undesirable behavior. Figure 36 shows that objects received through service interactions may be internally referenced and then sent to other components through successive service interactions.

Figure 36: Propagation pathways in a component. A component may receive an object coming through provided or required services, and pass them to other components through provided or required services.

“s can be seen, a component may pass objects in any direction . In the case of a Managed object, a component may end up coupling other components by passing them Managed objects that they become unknowingly coupled to. Furthermore, because components are not obligated to be aware of Managed objects75, they may (unknowingly to themselves) be passing Managed objects to other components. Indeed, one of the framework s tasks is to ensure consistency, and to do so,

73 Indicating that the component behaves prope rly and re leases managed obje cts whe n it doe s not is conside re d a software bug in the compone nt.

74 Fine -grain code -analysis may be used to indicate if a Manage d object is in fact re fe renced and if that re fe re nce is he ld by the compone nt or propagate d to othe r compone nts .

75 Our approach re lie s on conce ntrating programming e fforts for dynamism on critical parts of the archite cture , while le tting the frame work e nsure consiste ncy in parts of the archite cture that are not programme d for dynamism.

components that knowingly or unknowingly reference Managed objects must release them when necessary, by forceful destruction if needed.

There are two cases that the framework considers when analyzing potential propagation.

The first one is when the component is aware of Managed objects and handles them properly. In this case, and only for Managed objects, propagation is indicated in the component s implementation class. Should the component receive a managed object and pass it to another component, the component indicates this information using either a metadata file or using annotations in its implementation class76. A simple example using annotations is given in Figure 37. As can be seen, the component implementation (which provides a simple proxy service) indicates propagation using, as origin, the Service type (i.e., service interface) of the propagated managed objects77, and as destination, the Provides service annotation. For components that are aware of Managed objects, the framework expects them to properly declare propagation. If this is not done, then the framework considers this to be a software bug in the component s implementation.

/* import headers */

import fr.imag.PrinterService;

@Provides (propagates=PrinterService) public class PrinterProxy{

@Requires PrinterService printer;//injected dependency

/*method definitions start here*/

PrinterConfigurator getConfigurator(){

return printer.getConfigurator();

} //…

}

Figure 37: Component implementation example showing how to indicate Managed object propagation from a required service to a provided service.

The second case of propagation is with components that are not aware of Managed objects. If propagation is not handled, the worst case scenario is that the component propagates managed objects through all services it requires and provides, thus, transparently coupling all components it interacts with. In this case, once coupling becomes transparent and hidden to components, it is not possible for the components to properly release the managed objects78. Indeed, transparent

76 The inde pe nde nce between two diffe re nt Se rvice Contracts means that we cannot spe cify this information in the Se rvice Inte rface be cause some compone nt imple me ntations may propagate Manage d obje cts while othe rs do not.

77 The limitation of using the Se rvice Inte rface as that propagation is calculate d using imple me ntations and not instance s, thus, it is le ss fine -grain. Howe ve r, the advantage is that it is simple r to use , and it ope ns up the possibility of

6.2 Decoupling component instances

propagation of managed objects may lead to the forced destruction of all components reachable from the propagating component.

Component destruction is not problematic for components that have been identified by the architect at design-time; however, transparent propagation is still problematic because components that are programmed to be aware of dynamism may not know they are receiving a propagated Managed object. Indeed, there is a lack of a protection barrier against such cases. Such a barrier is needed in order to ensure that a component will never hold a dangling reference caused by a hidden Managed object.

The only safe attitude, from the framework s perspective, is to calculate the contamination caused by the hidden propagation of Managed objects. This is discussed below.

6 .2 .7 .1 Im pr oving pr opagation analy sis

There are multiple ways to improve analysis regarding the propagation of Managed objects.

Using the Service Contract (i.e., the Services implementation classes , we can compare if a class that defines the Managed Object is reachable through other Service Contracts with which an unaware component interacts79. If it is not a reachable class (i.e., the class is not contained in the transitive closure of reachable classes of the second services Service Interface), then it is impossible for it to be propagated through that service. Such a calculation needs to be done for all services the component interacts with (both consumed and provided). However, if two service contracts have an overlapping class that is used to define a Managed object, then propagation is possible. If propagation is possible, the next calculation is to verify if propagation is through a Free object. If not, that means that the component transparently propagates a Managed object through an explicitly declared Managed object, and is thus no harm to other components. On the other hand, if it propagates the Managed object through a Free object, propagation becomes transparent and transitively couples other components. Because of the transitive nature of propagation, a contaminated component (i.e., a component that has received a hidden managed object) must be analyzed using the same procedure to see if contamination is further propagated.

Static code analysis is another way of analyzing propagation. The idea is to analyze the component s source code to effectively deduce if propagation occurs. We explain this approach in more detail in section 8.3.4.

6 .2 .7 .2 D e sign-tim e c onside r ations of pr opagation analy sis

In general, a component that is not programmed for handling dynamism should never be allowed to interact with services that define managed objects. This can be easily verified: if the component requires or provides a service that declares managed objects (i.e., the service interface has a Managed object annotation), it should implement a notification callback method and handle

compone nt receives a hidde n Managed object that is transparently propagated by an unaware propagating compone nt, the re ceiving component will not be e xpe cting the notification to de couple from such an obje ct e ve n if the Frame work should se nd one .

79 Note that the transparent propagation of Managed objects only occ urs through components that re ceive Managed obje cts (the y are de fined in the Se rvice Interface) and are unaware of the y must re lease the m or indicate the y propagate the m (i.e ., the y do not re ce ive notifications from the frame work to re le ase the m nor do the y spe cify propagation).

them correctly. If it does not, the designer should be warned and the component should be changed.

Should a component receive a Managed object and not be aware of notifications, it should be verified that the component does not propagate the managed object. If propagation does occur, the propagation path should be determined and the object through which propagation occurs in the destination Service Interface should be identified. The destination Service should have its Service Interfaces object declared as a Managed object (using @Managed annotation) allowing components that use that service to be aware of coupling. Thus, even though the propagating component is unaware of propagation, other components can still be aware because the Service Contracts properly inform them of Managed objects.

Finally, particular attention needs to be paid to components that interact with Managed objects because of the risk of propagating the objects. When designing services, architects and developers should be attentive to identifying Managed objects in order for verification processes to be effective. When transparent propagation occurs, it can be extremely hard to identify how far the objects have been propagated, potentially causing large parts of the application to be invalidated in an effort to ensure consistency and avoid dangling references.