Keep your code structure clean

 

As an architect or a lead developer
responsible for the structure of a code base, you spend time creating a clean
structure for your code. The challenge is to make sure that the intentions you had when creating the structure won’t be violated in the future, what is often named design
erosion
or architecture erosion.

 

Let’s take a real-world application
such as Octopus Micro Finance Suite,
an open-source application developed by the Octo Technologies company. Typically,
in such a 3 tiered application, the UI code shouldn’t access directly the
database. Concretely, the code of the assembly Octopus.GUI shouldn’t use directly the class Octopus.Shared.DatabaseHelper.

 

As shown in the screenshot below, with
NDepend you just have to right-click the cell on the Dependency Structure Matrix that represents the dependency that is forbidden, and
select Generate a CQL constraints that
warns if this dependency exists
. The CQL rule generated basically says:

 

I’ll warn if
there is an assembly named Octopus.GUI that
is using directly a type named Octopus.Shared.DatabaseHelper.

 

 

As in every deny system, there is also a possibility to have some permit only CQL rules. Maybe, the architects
of the Octopus project want to make
sure that the assembly System.Drawing
is only used by the assembly Octopus.GUI.
Here, the CQL rule says that:

 

I’ll warn if
there is an assembly that is not named Octopus.GUI
and that is using directly an assembly named System.Drawing.

 

 

The CQL language presents some smarter
usage conditions to write smarter
constraints. For example, the architects of the Octopus project might want to make sure that no SQL connections are
created outside the type System.Data.SqlClient.SqlConnection.
Here, the CQL rule says that:

 

I’ll warn if
there is a method declared outside the type Octopus.Shared.ConnectionManager
that is creating an instance of the class System.Data.SqlClient.SqlConnection.

 


 

Another usage conditions is the derivation. 
The following CQL rules says that:

 

I’ll warn if
there is a class declared outside the assembly Octopus.GUI that derives from System.Windows.Forms.Form.

 

In the same spirit, CQL supports the Implements condition to constraint which
classes implements a certain interface.

 

Finally, another very useful usage condition is the field writing one.
As shown in a previous post, you might want to ensure that the only way a field
is written is by calling its corresponding property setter. Doing so, it is easier to maintain and debug the field state, you don’t have to put breakpoint everywhere the field is assigned.

Normal
0

false
false
false

EN-US
X-NONE
X-NONE

MicrosoftInternetExplorer4

<!–
/* Font Definitions */
@font-face
{font-family:”Cambria Math”;
panose-1:2 4 5 3 5 4 6 3 2 4;
mso-font-charset:0;
mso-generic-font-family:roman;
mso-font-pitch:variable;
mso-font-signature:-1610611985 1107304683 0 0 159 0;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;
mso-font-charset:0;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:-1610611985 1073750139 0 0 159 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-parent:”";
margin-top:0in;
margin-right:0in;
margin-bottom:10.0pt;
margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:”Calibri”,”sans-serif”;
mso-fareast-font-family:”Times New Roman”;
mso-bidi-font-family:”Times New Roman”;}
pre
{mso-style-priority:99;
mso-style-link:”Préformaté HTML Car”;
margin:0in;
margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:”Courier New”;
mso-fareast-font-family:”Times New Roman”;}
span.PrformatHTMLCar
{mso-style-name:”Préformaté HTML Car”;
mso-style-priority:99;
mso-style-unhide:no;
mso-style-locked:yes;
mso-style-link:”Préformaté HTML”;
font-family:”Courier New”;
mso-ascii-font-family:”Courier New”;
mso-hansi-font-family:”Courier New”;
mso-bidi-font-family:”Courier New”;}
.MsoChpDefault
{mso-style-type:export-only;
mso-default-props:yes;
font-size:10.0pt;
mso-ansi-font-size:10.0pt;
mso-bidi-font-size:10.0pt;
mso-ascii-font-family:Calibri;
mso-hansi-font-family:Calibri;}
@page Section1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;
mso-header-margin:.5in;
mso-footer-margin:.5in;
mso-paper-source:0;}
div.Section1
{page:Section1;}
–>

/* Style Definitions */
table.MsoNormalTable
{mso-style-name:”Tableau Normal”;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:”";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin:0in;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:”Calibri”,”sans-serif”;
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:”Times New Roman”;
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:”Times New Roman”;
mso-bidi-theme-font:minor-bidi;}

WARN IF Count
>
0 IN SELECT METHODS WHERE

  IsDirectlyWritingField  “Octopus.CoreDomain.ClientGroup.leader” AND

  !FullNameIs "Octopus.CoreDomain.ClientGroup.set_Leader(Person)"

 

CQL rules are stored inside the
NDepend project file. You can also store CQL rules directly in the source code
as shown here.
All rules will be verified each time NDepend will analyze the project and
if some rules are violated, they are enumerated in the report built during the
analysis.

 

All resemblance with the way how xUnit tests tools are working is intended. xUnit tests test the code to prevent correctness regression. CQL rules test the structure to prevent architecture erosion.

 

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    This is cool Patrick. I’m honestly still using the old OSS version of NDepend just for CC numbers, but now you’ve got me thinking about getting this applied and into the build for my next project.

  • karl

    I agree this really is cool. I have to admit, I find NDepend a little too intimidating to use – and I bet I’m not the only one. Like Jeremy I’ve used the OSS version for various metrics, but haven’t taken the plunge to the new version. (a) where do you recommend starting (is there a simple sample project available with a detailed explanation of the ndepends output, that would be awesome?) and [b] do you feel that there are opportunities for you to improve the tool to reach a wider audience – specifically with respect to ease of use? Could be some good blog posts :)

  • http://www.NDepend.com Patrick Smacchia

    Karl, we are currently working hard to improve the UI ergonomy and make the tool usability very close to what VisualStudio propose. Actually, it is our primary goal to reach a wider audience with more ergonomy and documentation. The release v2.6 with the improved UI should be available mid dec.

    Basically we are adding a start page, a project properties and a error list panels to VisualNDepend.

    The current version already comes with a help panel that explains how to get started with the most common scenarios. It is still perfectible and all feedbacks are highly appreciated.

  • http://www.grantpalin.com Grant Palin

    Very neat. Looks to be a useful project management tool. Do you use the paid version of the software? Or is the trial “good enough”?