Software developers are always thankful for tools that do not interfere too much with their work habits. Software metrics can offer some feedback on the quality and results of design decisions, and help developers move towards an engineering approach to software. Metrics are a useful resource to help determine whether software meets desired quality characteristics. Although many types of metrics have been devised, design metrics for object orientation have reached one of the highest levels of maturity because their relationship to lower maintenance efforts, lower defect rates, and other benefits has been demonstrated repeatedly in studies. As such, basic design concepts such as encapsulation, inheritance, polymorphism, and class complexity are known indicators of software quality.
As UML becomes a de facto standard notation for software documentation, effective design metrics increasingly must work with UML diagrams as input. Some tools have the ability to calculate design metrics from UML diagrams, but this activity can benefit from relying on Web services created with an open-source solutions to calculate the metrics. The Web service we created uses SOAP messages, typically conveyed using HTTP, with XML serialization. Using this technique, a Web service that implements the calculation of UML metrics can be inserted in any development environment and serve as a source of early feedback to architects and developers.
XMI and UML diagrams
Most UML modeling tools are capable of importing and exporting models or diagrams (see a sample UML class diagram in Figure 1) using the XMI format. XMI is an XML dialect that includes tags to represent UML diagrams and their components. Listing One presents a sample XMI code extract that corresponds to the class diagram in Figure 1 (exported as an Example.xmi
file).
Figure 1: Class diagram example.
The tag <packagedElement>
with the attribute type=Class
is used to represent classes, while <ownedOperation>
, <ownedAttribute>
, and <generalization>
represent attributes, operations, and inherence associations. This example is pretty good because UML class diagrams are most-oftent used as documentation and they are totally equivalent to the structure of code.
<?xml version="1.0" encoding="UTF-8"?> <xmi:XMI xmi:version="2.1" xmlns:uml="http://schema.omg.org/spec/UML/2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1"> <uml:Model xmi:type="uml:Model" xmi:id="themodel" name="example"> <packagedElement xmi:type="uml:Package" xmi:id="example" name ="example"> <packagedElement xmi:type="uml:Class" name="Person" xmi:id="person" visibility="public"> <ownedAttribute xmi:type="uml:Property" name="Name" xmi:id="name" visibility="private"> <type xmi:type="uml:PrimitiveType"href="http://schema.omg.org/spec/UML/2.1/uml.xml#String"/> </ownedAttribute> <ownedAttribute xmi:type="uml:Property" name="Age" xmi:id="age" visibility="private"> <type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#Integer"/> </ownedAttribute> <ownedOperation xmi:type="uml:Operation" name="SetName" xmi:id="setname" visibility="public" isAbstract="false"> <ownedParameter name="return" xmi:id="return_1" direction="return"> <type xmi:type="uml:Class" xmi:idref="datatype_0"/> </ownedParameter> <ownedParameter xmi:type="uml:Parameter" name="Name" xmi:id="op_param_1" direction="in"> <type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#String"/> </ownedParameter> </ownedOperation> <ownedOperation xmi:type="uml:Operation" name="GetName" xmi:id="getname" visibility="public" isAbstract="false"> <ownedParameter name="return" xmi:id="return_2" direction="return"> <type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#String"/> </ownedParameter> </ownedOperation> </packagedElement> <packagedElement xmi:type="uml:Class" name="Driver" xmi:id="driver" visibility="public"> <generalization xmi:type="uml:Generalization" xmi:id="gene_person" general="person"/> <ownedAttribute xmi:type="uml:Property" name="LicenceDate" xmi:id="licencedate" visibility="private"> <type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#String"/> </ownedAttribute> <ownedAttribute xmi:type="uml:Property" name="MyCars" xmi:id="attrib_mycars" visibility="private" association="mycars" aggregation="none"> <type xmi:type="uml:Class" xmi:idref="car"/> <lowerValue xmi:type="uml:LiteralString" xmi:id="multi_lowmultipli" value="*"/> <upperValue xmi:type="uml:LiteralString" xmi:id="multi_up" value="*"/> </ownedAttribute> <ownedOperation xmi:type="uml:Operation" name="ObtainLicence" xmi:id="obtainlicence" visibility="public" isAbstract="false"> <ownedParameter name="return" xmi:id="return_3" direction="return"> <type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#Boolean"/> </ownedParameter> <ownedParameter xmi:type="uml:Parameter" name="date" xmi:id="param_date" direction="in"> <type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#String"/> </ownedParameter> </ownedOperation> <ownedOperation xmi:type="uml:Operation" name="BuyCar" xmi:id="buycar" visibility="public" isAbstract="false"> <ownedParameter xmi:type="uml:Parameter" name="newCar" xmi:id="param_newcar" direction="in"> <type xmi:type="uml:Class" xmi:idref="car"/> </ownedParameter> </ownedOperation> </packagedElement> <packagedElement xmi:type="uml:Class" name="Car" xmi:id="car" visibility="package"> <ownedAttribute xmi:type="uml:Property" name="Model" xmi:id="model" visibility="private"> <type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#String"/> </ownedAttribute> <ownedAttribute xmi:type="uml:Property" name="Price" xmi:id="price" visibility="private"> <type xmi:type="uml:Class" xmi:idref="datatype_1"/> </ownedAttribute> </packagedElement> <packagedElement xmi:type="uml:Association" xmi:id="mycars" visibility="private"> <memberEnd xmi:idref="attrib_mycars"/> <ownedEnd xmi:type="uml:Property" xmi:id="end_mycars" association="mycars" visibility="private" type="driver" aggregation="none" isNavigable="false"/> <memberEnd xmi:idref="end_mycars"/> </packagedElement> <packagedElement xmi:type="uml:Dependency" xmi:id="dep_driver_car" client="driver" supplier="car"> </packagedElement> </packagedElement> <packagedElement xmi:type="uml:DataType" xmi:id="datatype_1" name="float"/> <packagedElement xmi:type="uml:DataType" xmi:id="datatype_0" name="void"/> </uml:Model> </xmi:XMI>