Tuesday, November 17, 2009

Inside Qt Part 1 : QtCore

Qt is a cross-platform application development framework, widely used for the development of GUI programs ,and also used for developing non-GUI programs such as console tools and servers.

Qt consists of several modules, and each one rely on QtCore, this module contains all basic classes like Containers,String,Smart Pointer,Multithreading,Localisation and other funcionalities.

Let's discover with CppDepend the QtCore module.







Namespace Layering:

Modelizing components of a code base with namespaces is a better idea to gain clear architecture, but in the C++ world this logical artifact is not enough used, a few C++ open source projects use namespace layering to modularize the code base.

Not using namespaces not implies that a library is bad designed,it's a choice of library designers and each project is specific, but generally using namespaces improve the design quality.

QtCore provide many classes that can be isolated in namespaces like Containers, IO,Multithreading and so one, and maybe for historical reason the namespaces are not enough used.


CppDepend provide DSM graph, and we can triangularize this matrix to focus under red borders highly dependency cycle.







A dependency cycle exist between namespaces, having this dependency can be not problematic but avoiding it enforce loose coupling,this interesting post explain the benefit of layering.

Which paradigme mostly used?

C++ is a multi paradigm langage and it's very important to know for a defined project which paradigm is used.

Lets search for global functions:

SELECT METHODS WHERE IsGlobal AND !IsInTierProject






What about classes and structures?

SELECT TYPES WHERE (IsClass OR IsStructure ) AND !IsTemplate AND ! IsInTierProject AND !IsGlobal






And concerning generig paradigm:

SELECT TYPES WHERE IsTemplate AND ! IsInTierProject






QtCore use all the paradigms proposed by C++, doing that is interesting to exploit the advantages of each one, but in such case we have to focus more on design to avoid complicated module.


Inheritance:

For POO pradigm the inheritance can be very used to exploit polymorphism concept, but overusing it can implies a high coupling between classes, so the inheritance must be used only if it's necessary.

SELECT TYPES WHERE NbBaseClass >0






We can observe that inheritance is not overused in this module.

And what about multiple inheritane? using it increase complexity ,and we have to use it carefully.

Let’s search for class with many base classes.

SELECT TYPES WHERE NbBaseClass >1







Only 4 classes derive from more than one classe.

Low coupling and Abstractness:

low coupling is desirable because a change in one area of an application will require less changes throughout the entire application. In the long run, this could alleviate a lot of time, effort, and cost associated with modifying and adding new features to an application.

Using abstract classes can improve the low coupling and we can evaluate the abstractness of a defined module by the following metric :

A = Na / Nc

Where:

* A = abstractness of a modulke
Zero is a completely concrete module. One is a completely abstract module.
* Na = number of abstract classes in the module.
* Nc = number of concrete classes in the module.

For QtCore the Abstractness is equal to 0.01806589 , so this module is more concrete than abstract.

Let's search for abstract classes:

SELECT TYPES WHERE IsAbstract






Only a few classes are abstract, we can consider that's normal for this module because it provides many technical utility classes and for such module it must be more concrete than abstract.


Type Cohesion:

The single responsibility principle states that a class should have more than one reason to change. Such a class is said to be cohesive. A high LCOM value generally pinpoints a poorly cohesive class. There are several LCOM metrics. The LCOM takes its values in the range [0-1]. The LCOMHS (HS stands for Henderson-Sellers) takes its values in the range [0-2]. Note that the LCOMHS metric is often considered as more efficient to detect non-cohesive types.
LCOMHS value higher than 1 should be considered alarming.

SELECT TYPES WHERE LCOMHS > 0.95 AND NbFields > 10 AND NbMethods >10 AND !IsGlobal ORDER BY LCOMHS DESC







Only very few classes are considered as no cohesive.

QObject:

QObject is the heart of the Qt object model,it provides a usefull mecanism to facilitate the developement,The central feature in this model is a very powerful mechanism for seamless object communication called signal and slot.

Another usefull mecanism is the fact that QObjects organize themselves in object trees. When you create a QObject with another object as parent, the object will automatically do an insertChild() on the parent and thus show up in the parent's children() list.

this following dependency graph shows that for each creation of QObject, the setParent is invoked.








Another intersting mechanism concern the dynamic casting, when we execute the following CQL query :

SELECT METHODS WHERE IsDirectlyUsing "Keywords.dynamic_cast".

The result is empty, so what happen QtCore never use dynamic casting mechanism?

The qobject_cast() function behaves similarly to the standard C++ dynamic_cast, with the advantages that it doesn't require RTTI support and it works across dynamic library boundaries.


which classes of QtCore are derived from QObject?

SELECT TYPES WHERE DeriveFrom "QObject"






Immutability:

Basically, an object is immutable if its state doesn’t change once the object has been created. Consequently, a class is immutable if its instances are immutable.

There is one killer argument for using immutable objects: It dramatically simplifies concurrent programming. Think about it, why does writing proper multithreaded programming is a hard task? Because it is hard to synchronize threads accesses to resources (objects or others OS things). Why it is hard to synchronize these accesses? Because it is hard to guarantee that there won’t be race conditions between the multiple write accesses and read accesses done by multiple threads on multiple objects. What if there are no more write accesses? In other words, what if the state of the objects threads are accessing, doesn’t change? There is no more need for synchronization!

Which classes of QtCore are immutable?

SELECT TYPES WHERE IsImmutable






243 classes are immutables.


Most used types:

TypeRank is a metric that can be used to know the popularity of a type.

Which classes are mos used?

SELECT TOP 15 TYPES WHERE !IsGlobal ORDER BY TypeRank






QString is the most used one, we can search for all classes that use it.

SELECT TYPES WHERE IsDirectlyUsing "QString"






Almost the entire module use it, but the recurent question is why not using std::string, and why using a specific class and not standard one?

Maybe there are many reasons, and one reason is that the C++ standard was finalized late in 1998, it then took some time until all systems actually provided a correct C++ library.


Decoupling data and behavior:

Qt use many classes to store data, their names end by "Private".

SELECT TYPES WHERE NameLike "Private$"






This pattern disociate data and behavior, for example the following dependency graph shows the relation between QThreadPool and QThreadPoolPrivate.







Localization:

Localization is the process of adapting to local conventions such as date and time presentations, and QtCore provides QLocale classe for this functionality.
Let's search for classes using it:

SELECT TYPES WHERE IsDirectlyUsing "QLocale"






We can observe that Date,Time,String and others use it to localize their data.

Multithreading:

QtCore provides also all classes needed for multithreading.
We can search for calsses responsables of creation of threads, for that we can choose the _beginthreadex function in WindowsAPIGlobalMembers, right click and choose the option "Who is directly using me".







And there's the result:






So the creation of thread is centralized in QThread class.

Smart Pointer:

QtCore provide many classes to manage Smart Pointer, each one can be used for a specific context.






Conclusion:
QtCore is the base module of Qt, it provides many usefull classes for many needs, it's well designed and easy to understand and use.

No comments:

Post a Comment