Component

From Java4c

Contents

Navigation

Components and modules, re-using

A software should consist of more as one component. Each component should be able to describe, program and test independent of the application which uses it. A component may be able to use in several applications. Then it is reuseable.

Modules are the finer granularity inside components or inside the core of the application. Each module should be able to describe, program and test independently too. Modules may be one C/h-file or a package in Java or some related files.

A class in ObjectOrientation is the more finer granularity inside modules. A class in the C-programming is a logical coherence between one data structure and related subroutines. One class may be presented exactly with one source-file.

Dependencies between components, modules, classes

If another class is used inside a class, it depends on it. Formally it depends on the signature of the methods of the class. Really the functionality depends on the functionality of the called methods.

For a independent test of a class, module or component it may be necessary to abstract the functionality of the depending stuff. The behavior of the depending stuff should be replaced by a simulation or emulation.

Dependencies defines components

If a component need the presence of another component while compiling or linking, then the component depends on the other component formally. Components should be tailored to specified other components. If any other component is need only for a special function, which isn't the main stream functionality of the component, it is disagreeable. The user of the component should attend to the other component, which isn't need really. It is additional work to do without benefit.

Components can be depended on any common functions of a platform, which are present anytime. For example all base class of a Java Virtual Machine and its rt.jar library can be used in the Java-sources. Then the component may be designated as independent of any others.

If a component depends on another specified component, it builds a system of components. Such a component-system should not be complex. Dependency-breaker are need. The dependency breakers allow a formally translation (compilation) without the presence of other complex components. For running (linking), any incarnation of the components behind the dependency-breaker should be present. But that components may be replacements for simulation etc. if necessary.


Dependencies in a application

There are horizontal and vertical dependencies: If a class/module/component can be created, described and tested independent on another class/module/component, it is deeper in vertical or parallel in horizontal layer. If a class/module/component needs another one, it is above that in vertical layer. It needs means, in the real application it is associated to it and calls some methods from there. For the independently test all needed classes/modules/components may be able to replace.

Interfaces as dependency-breaker

There is a problem: Module_A needs some methods from Module_B and on the other hand Module_B needs some things from Module_A. Both modules are parallel in layer, but there are not able to develop and test independently. - Either the both modules are not two separated modules, the functionality should be combined in one module. - Or it should be separated using interfaces.

Another Aspect of Interfaces: A Component should not need a special other component. It should be more commonly in its dependency-necessities. A selection of the other associated components should be possible, for example for simulation and real usage, for different platform necessities etc.

  • While compiling only the interfaces should be present.
  • While static linking in C/C++ or starting an application in Java or C++ with dynamic libraries any incarnation of interface-implementors can be used. Others for testing and for several application goals.
  • A symbolic linkuage is possible: The selection of a dynamic library or implementation class can depend on the presence of a special library or jar-file in the file system. It is possible too to select a implementor by parametrizing, especially with a identifier string. In this kind selecting on runtime is possible.

Interfaces in Java

The interface is a language-element of Java. It defines methods with its signature, but without implementation. The description, "what should the method do, which argument values are expectable, meaning of the return value" belongs to the method anyway. In C++ interfaces are able to create in a similar kind as Java. It is a class with only virtual abstract methods and without any implementation:

class InterfaceExample {  //C++-interface
  virtual int aMethod(int arg) = 0;
};

Selecting implementors while startup

TODO

Selecting implementors symbolic

TODO Class.forName()

Classic C - Headerfiles as interface

The classic C programming knows headerfiles, which ones play the role of interfaces: Function prototypes has the same appearance as a method definition in a Java-interface or a virtual abstract methods:

extern int aFunction(int arg);

The difference to Java and C++-virtual-methods is: It is static linked. There can be only one implementation in a executable, whereby in Java and C++ the interface can be implement by several classes which are instantiated independently. It is a dynamic link.

But the principle of dependency-break is the same.

Classic C- struct forward declaration as dependency break

In C and C++ there is a nice possibility to prevent to many include-necessities:

struct TheType_t;
typedef struct Example_t{
  struct TheType_t* pointer;
} Example;

Inside the Example-struct a pointer of TheType is need. But TheType itself may left unknown. It isn't necessary to know the type while compiling this struct. It is not necessary to include the typedef of TheType

If the pointer is used in the implementation (the C-file), then the type should be known. The implementation-File includes the definition of:

 typedef struct TheType_t{
   int someStuff;
 }Thetype;

Now the compiler checks the matching of struct TheType_t to TheType with its given definition. The TheType_t is the tag-name of the struct where TheType is the really type name. The writing-style with _t-suffix is recommended and usual but not a fix rule.

The forward declaration of a pointer-type straightens a complex dependencies of header files. In Java there is not a adequate possibility. A Java-interface is the way of straighten still.

Criterion for Components

  • Able to define and describe as entity.
  • Able to test as entity.
  • Dependencies of parts to other components: If any new part creates a new dependency to a foreign component, it should be realized as critical. Either the new dependency is desired, or the part should not be a part of this component.
  • Conglomerate of several functionality: It is okay, if the modules doesn't need other components (see dependencies). A component can contain a functionality, which is not need in the typical use-cases, but it is offered for special usages.
  • Frequently changes in conglomerate parts: Any change in the sources of the component builds a new release of the whole component, which should be checked for relevance for all usages. Parts, which are frequently changed, but they are not a core functionality of the component, should be dissolved from the component therefore.
  • Self-reliance: The same functionality should not scattered to several components. Only one component should be responsible to that functionality.
Personal tools