Thursday, December 3, 2009
Recently i read a famous linus torvalds opinion about C++, where he wrote:
"C++ is a horrible language. It's made more horrible by the fact that a lot of substandard programmers use it, to the point where it's much much easier to generate total and utter crap with it. Quite frankly, even if the choice of C were to do *nothing* but keep the C++ programmers out,that in itself would be a huge reason to use C."
Thursday, November 19, 2009
But when i discovered GRASP patterns , i advice any one interested to improve his skills design to look at this patterns, it gives a design fondamental rules.
Irrlicht is a 3D engine library that use many GRASP concepts, let's discover with CppDepend the benefits of using this kind of patterns, and to show using of GRASP concepts we will focus on the namespace irr::gui.
Tuesday, November 17, 2009
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.
Monday, November 2, 2009
I searched for the characteristics of this library and i found the following definition:
OGRE (Object-Oriented Graphics Rendering Engine) is a scene-oriented, flexible 3D rendering engine written in C++ designed to make it easier and intuitive for developers to produce applications utilising hardware-accelerated 3D graphics. The class library abstracts the details of using the underlying system libraries like Direct3D and OpenGL and provides an interface based on world objects and other high level classes.
Wednesday, October 7, 2009
Wednesday, September 23, 2009
"The POCO C++ Libraries are a collection of open source class libraries for developing network-centric, portable applications in C++. POCO stands for POrtable COmponents. The libraries cover functionality such as threads, thread synchronization, file system access, streams, shared libraries and class loading, sockets and network protocols (HTTP, FTP, SMTP, etc.), and include an HTTP server, as well as an XML parser with SAX2 and DOM interfaces and SQL database access. The modular and efficient design and implementation makes the POCO C++ Libraries well suited for embedded development."
Saturday, September 19, 2009
Let’s discover the benefits of this Pattern using CppDepend, and for that we analyze the following example.
in this example we have a code source before and after refactoring, you can copy the code into two distincts files factorybefore.cpp and factoryafter.cpp.
To analyze this example with CppDepend, do the following steps:
- Lanch VisualCppDepend.exe and create new project.
- Use “Create Project Description “ Button to lauch the project maker wizard
- Add Project to solution.
- Add Files to project created
- Save as “Factory.sl”
- In VisualCppDepend use “Browse” button to specify Factory.sl file.
- Launch the analysis.
After the analysis of the example before using factory pattern, we analyze it after the modifications, for that we have to change the description of the project by removing “factorybefore.cpp” and adding “factoryafter.cpp”.
CppDepend provide an interesting functionality to compare between two version, in our case we compare the project before and after refactoring and there's the result.
we can see that there are some added new classes in the browser characterized by the Bold Style and there's also a modification in dependency matrix.
Where WindowsButton class is created?
To answer to this question let’s execute the following CQL request:
SELECT METHODS WHERE CreateA "WindowsButton" ORDER BY DepthOfCreateA
So we can observe that before refactoring, the class is created in many places, but after refactoring the creation is isolated in WindowsFactory, the responsibility of the creation is now isolated and it impact the cohesion, so we have a high cohesion than before.
What the impact for coupling?
Using Matrix can help to detect coupling between projects and classes.
If you look at the intersection between main method and MotifButton class we observe a red “-“sign, so we lose a dependency between Main and other classes like WindowsButton, MotifButton.
Let’s discover the dependency graph before and after:
So the global methods are now isolated form concretes classes used, and we have a low coupling so we can add another family of classes without changing the client that use them, only the factory will be changed.
Abstract Factory can improve the cohesion and coupling of classes.
Sunday, September 6, 2009
A view of the work achieved
SELECT METHODS WHERE CodeWasChanged OR WasAdded
The following treemap shows in blue, new methods (i.e WasAdded) and methods that have been refactored (i.e where CodeWasChanged). A rectangle represents a method and the size of the rectangle is proportional to the size of the method (in terms of Code Line ). It is pretty impressive to see that a big part of the framework is still evolving.
The Info panel of CppDepend shows that MFC 2008 is bigger twice than MFC 2005
SELECT TYPES WHERE WasAdded
367 new types added including:
• Ribbon Control
• Outlook Alert
• Dialog Boxes
SELECT NAMESPACES WHERE WasAdded
Only 1 namespace was added it contains classes to integrate Winform into MFC.
Methods where visibility changed
Only the visibility of the CHtmlEditCtrl destructor was changed from protected to public.
It was a design bug in MFC 2005, you can discover here why it was problematic.
All classes relative to ISAPI were removed; it’s a break change that can be very embarrassing for developers who used them before.
The major evolution of MFC includes a new types to support modern user interface (UI) elements such as the Office Fluent UI, docking windows and MDI tabbed windows similar to those used in some releases of Visual Studio, enhanced toolbars, a rich new set of controls, support for controlling the overall visual style, support for desktop alerts, and much more.
but no big changes concerns the MFC design,it's true that MFC now use more manager classes as controlers than before
but the design of the new functionalities still unchanged, for example only one namespace is added.
Sunday, August 9, 2009
Solution without design:
For this first solution the design is ignored and only one class named CDataProcessor is used to:
- Get data from file.
- Processing data.
- Print result.
And the main method invokes the methods of this class.
drawback of this solution:
Low cohesion: CDataProcessor class has many responsibilities so we can’t easily reuse algorithm in other application.
High coupling: the processing is high coupled with console and also with data provider.
- High Cohesion:
To improve cohesion each responsibility must be assigned to a different class so we need three classes:
CFileProvider: To get data from File.
CDataProcessing: To process data, and this class can use other classes to complete processing, but to simplify the design we consider that's sufficient for our processing.
CResultReporting: To report result to file.
So each class has its own responsibility, there are advantages of this design:
- Easy to understand classes.
- Easy to maintain.
- Easy to reuse classes in other applications.
- Low coupling:
What happen if data exist in database not in file, in our last design our application is high coupled with file provider.
To resolve this problem we need an interface that provide methods to get data from anywhere , and for the case of file we need class that implement this interface.
For that using NVI can be good solution, so we need an interface IDataProvider
And CFileProvider inherit from IDataProvider to implement GetDataFromImpl, and the same design can be used for CDataProcessing and CReportResult.
Here’s the new collaboration between classes after refactoring:
- Class Factory:
In the latest design the creation of concrete instances of IDataProvider,IDataProcessing and IReportResult are created by Main method.
A better approach is to assign this responsibility to a factory class so a logic to instanciate a family
of instances needed is isolated.
The orchestration between all classes is implemented in the main method.
it's better to assign this responsability to a Controller class, so we can use it in other applications.
The controller needs three classes to interact with them, so the question is how we bind instances to controller?
Two solutions can be used:
- Add method named BindInstances(IDataProviderPtr,IDataProcesingPtr,IReportResultPtr).
- Use template so the controller will be instantiated like that:
The difference between two solutions is that for the first one each DataProvider must inherit from IDataProvider, and for the second one CFileProvider need only the method GetData (Data&) even if it’s inherit from another class than IDataProvider.
Here’s the new collaboration between classes after refactoring:
Benefit of refactoring:
After refactoring this application became more flexible and we can use it for different scenario:
- Can get data from file,database,xml file,csv file,…
- Can process with many class not only one.
- Can report to console,file,….
Which libraries to use for this application?
In our application we need read/write to file, processing and write to console, in this case STL and Boost are in general sufficient.
Thursday, July 2, 2009
“You search for a C++ developer who master MFC, ATL, COM, and Database…” its sound like “You search for a C++ Guru”.
At this time I thought that’s normal and I must master all these skills, but after many years as C++ developer I knew that this kind of offers can indicate a high coupling of the project with external frameworks.
Using frameworks accelerate the development it can be used for GUI, database, files and others needs, but using it when it’s not necessary can complicate the project, for example for business layer we just need POCO objects.
Let’s see the impact of high coupling for different actors.
Human resource manager:
If a C++ project is highly coupled with external frameworks, the HR must search for C++ developer who master all the frameworks used, and now it’s very difficult to find a good C++ developer and find one who master other frameworks can be very difficult.
Architect and designer:
When the project is highly coupled with other frameworks we lose of flexibility, and any migration or adaptation of project to other context (WebService,Console,…) will be difficult.
Any framework has its difficulties and we need some time to master it, and adding complexity of other frameworks to the project can add an overhead.
For unit test it’s very difficult to isolate just our code and test it if it’s highly coupled with other frameworks.
So it’s nice to use frameworks to accelerate the development but use them carefully and avoid as possible unnecessary coupling.
Let’s analyze some open source project to discover what skills needed to integrate the development team.
Case I: Emule project (http://www.emule-project.net)
After analyzing emule with CppDepend we observe that it’s use MFC and ATL libraries
Let’s see if MFC is used in the whole project, for that we can ask CppDepend whitch classes use MFC classes and here’s the result:
we observe that MFC is used in the whole project, but how many classes of MFC are used and which ones are mostly used ( Gui,Containers,Archive,..)?
Many MFC classes are used and it concerns Gui,Internet,Archive and Containers.
The question is : Could you use the emule algorithm with other frameworks and in other contexts?
The answer is yes but it needs some overhead to disociate the busness layer from MFC.
If the algorithm was isolated into different namespace or maybe another module it can be reused in many other projects that needs the same behavior.
What about ATL ?
Emule use only some ATL classes, essentialy CString.
We can conclude that any developer who want to integrate the emule project must perform MFC library and ATL skill is not necesary.
Case II: OpenSTA project (http://sourceforge.net/projects/opensta/)
OpenSTA is divided into multiple projects and here's some project dependencies:
dividing project into diffierent modules can be very advantageous, it's better to isolate functionalities, we can use them in other projects and it simplify the complexity of project.
Which projects use MFC?
We observe that not all projects use MFC and the big ones d'ont use it.
Which MFC classses are used?
many MFC classes are used and especially OLE classes.
For OpenSTA project C++ developer who not master MFC can integrate the project.
Isolationg the using of external frameworks can be very advantageous for any actor, so keep it simple and avoid any unecessary coupling especialy for business layer.
Tuesday, June 9, 2009
The MFC framework is a powerful approach but using it impacts the design of the application, it’s very intrusive and we have to be careful of how we use it.
Let’s analyze MFC8 with CppDepend to discover its code quality and design.
CppDepend is a tool that simplifies managing a complex C++ code base. Architects and developers can analyze code structure, specify design rules, and plan massive refactoring, do effective code reviews and master evolution by comparing different versions of the code.
CppDepend supports the Code Query Language (CQL) for maximum flexibility. Basically CppDepend considers your code as a database and you can write some CQL statements to query and check some assertions on this database. As a consequence, CQL is similar to SQL and supports the SELECT TOP FROM WHERE ORDER BY pattern.
With CppDepend we analyze the quality of implementation and also the design of MFC.
A quality of implementation is important for developer who debug inside MFC,indeed not all things work as we like and sometimes we have to look inside the library code so if it’s not well implemented it complicate the task when debugging.
A design of MFC is very important for developers because it impact the design of the application because it's very intrusive.
MFC General Information's:
The dependency Graph shows that MFC uses 149 methods from ATL and 1014 from Windows API, and there’s general Information’s about MFC:
Let’s execute the following CQL request:
WARN IF Count > 0 IN SELECT FIELDS WHERE !NameLike "^m_" AND !IsGlobal
The blue squares represent the result of the query, so almost 50% fields don’t begin with m_”.
And what about methods naming:
WARN IF Count > 0 IN SELECT METHODS WHERE !NameLike "^[A-Z]" AND !(IsClassConstructor OR IsConstructor) AND !IsInTierProject AND !IsGlobal AND !NameLike "^~" AND !NameLike "^operator"
There are just some few methods that not begin with Upper case.
Cyclomatic complexity is a popular procedural software metric equal to the number of decisions that can be taken in a procedure.
We can also consider that a method is complex if NbLinesOfCode,NbParameters or NbBariables are great than a defined values.
SELECT METHODS WHERE (NbLinesOfCode > 100 OR CyclomaticComplexity > 20 OR NbParameters > 5 OR NbVariables > 8 )
So 706 methods are candidates to refactoring, but the request can be changed, it’s depending on the choice of the complexity criteria for each team.
SELECT METHODS WHERE NbLinesOfComment > 0
Almost all classes are commented so developers can have an idea of what a method does particularly when debugging inside MFC.
Let’s see if all complex methods are commented.
SELECT METHODS WHERE (NbLinesOfCode > 100 OR CyclomaticComplexity > 20 OR NbParameters > 5 OR NbVariables > 8 ) AND NbLinesOfComment ==0
There are just few complex methods not commented.
No existence of namespaces:
The namespace is an important concept to design application, it isolates functionalities under a module and provides a logical grouping, it can also make a library simple to use.
Unfortunately MFC don’t contain any namespace in spite of the existence of different functionality (GUI, OLE, Database, Containers …).
Global functions and variables:
MFC contains 786 global functions and 338 global variables, its lot for an object oriented framework.
SELECT TYPES WHERE NbBaseClass >0
Almost all class has at least one base class, it cause a high coupling between classes.
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.
WARN IF Count > 0 IN SELECT TYPES WHERE LCOMHS > 0.95 AND NbFields > 10 AND NbMethods >10 AND !IsGlobal ORDER BY LCOMHS DESC
31 types from 529 are considered non cohesive.
Dependency between Classes:
The option Direct & Indirect Weight of use the Dependency Structure Matrix is the perfect tool to let users know where the code structure is tangled with dependencies cycles.
The whole dependency matrix shows that almost all MFC types are coupled directly or indirectly.
The efferent coupling for a particular type is the number of types it directly depends on. Types with high efferent coupling are more complex than others,CppDepend propose a search panel, it’s like a wizard that help you construct query easily.
Let’s search for Types where efferent coupling is more than 30.
MFC separates data management into these two classes. The document stores the data and manages printing the data and coordinates updating multiple views of the data. The view displays the data and manages user interaction with it, including selection and editing.
In dependency graph CDocument and CView are mutually dependant and usually the model don’t have to know the View and it must be independent of any external framework.
The model has to be as simple as possible with simple types and without any unnecessary coupling.
The following CQL request demonstrate that CDocument is highly coupled with GUI classes:
SELECT TYPES WHERE IsDirectlyUsedBy "CDocument"
The goal is to reuse the same model in different projects (Console, Gui, WebService, …) and if our model is the CDocument we can’t reuse easily in other projects.
Never use CDocument as model but use it just as controller to refresh views.
MFC Automation Server :
CDocument can be used also as COM Component, but CDocument is coupled with CView and using CDocument as COM component can occur some unexpected limitations and problems.
When we instantiate a CDocument as COM Component a handle of view is created due to the coupling Doc/View so the number of instances to create is limited by the number of window handles that can be created, and the problem occur particularly if the instances are created in a no desktop session, in this case the number of handle that can be created is very limited by default.
Avoid using CDocument as COM component, keep it simple and use ATL instead it's more simple and flexible.
Use or don’t use MFC?
MFC is well implemented but not really object oriented and the classes are high coupled, so be careful when using it and avoid any unnecessary coupling, for example prefer using ATL for COM component and STL for containers.
It’s preferable to avoid as possible the coupling of your model with Doc/View concept, it make your design less flexible and add more complexity.
The goal is to spend more time in developing the business layer and isolate any technical layer will be very advantageous:
· Human resources department don’t need to spend a lot of time to search for MFC gurus; maybe just few MFC developers will be sufficient.
· Developers don’t add a complexity of a framework to the complexity of what’s they implement.
· Reusing easily the business layer in other context (Web Services, Console,…).
So keep it simple and isolate the impact of any technical framework used, for that be careful for any unnecessary coupling.
When the languages like Java or C# has been used by companies, a language like C++ became for many developers and mangers a complex and a bad language to avoid.
History of computer engineering can maybe explain this C++ vision:
Before internet explosion in 1990s, developing with C++ was very difficult due to the inexistence of technical documentation and feedback to resolve easily technical problems, so the team focused on technical layer.
We can understand why in this period the managers follow the technical approach and we looked for a C++ Guru to join the development Team.
After internet explosion we can found a many C++ documentation and feedback for technical layer but unfortunately the vision was not changed, and new developers spend lot of time searching for technical tricks.
The good way is to focus more time in the business layer which is the added value of a project and a technical layer must be just an infrastructure and we don’t have to spend a lot of time in it.
Imagine that we have to begin an application using COM Components, let’s see how two managers will realize this project.
C++ manager focused on technical layer
The first manager will first try to search for developers that master COM components it will take more time and energy but it’s obligatory for him to implement a project as he expect .
He will begin with a COM implementation and since the beginning of the project he add a complexity to it and also add useless dependency , even if the team contains just COM Gurus an overhead time will be spend in the COM Layer.
So finally this kind of manager will participate in an unpopularity of C++, every basic C++ developer will say “C++ is very complex”.
"Keep it simple" manager
"Keep it simple" manager
The second manager named “Keep it Simple” try to look for just one developer who master COM technology and the rest of the team are just a basic C++ developers.
This manager tell to his team to forget COM and just implement POCO objects ,simple classes that use a simple types to implement a business layer.
And just one developer who master COM technology develop a wrappers around the POCO objects.
So finally the “Keep it Simple” manager win a lot of time to look for developers and to implement the project and aproximatively the whole project is developed with a basic C++ concept, and isolate the COM technology complexity and limit dependency of a project .
With this approach every developer will say “WOW developing project that use COM technology is very simple”.
So try to avoid useless dependency; it can multiply the development time of a project, and a tool like cppdepend can help you to detect unecessary dependency .