SDA SE Wiki

Software Engineering for Smart Data Analytics & Smart Data Analytics for Software Engineering

User Tools

Site Tools


Smell Check

Identity Disharmonies

Data Class

Metrics

Short Name
WOC Weight of a Class
NOPA Number of Public Attributes
NOAM Number of Accessor Methods
WMC Weighted Method Count
  • Definition: (WOC < ONE THIRD) & { [ (NOPA + NOAM > FEW) & (WMC < HIGH) ] OR [ (NOPA + NOAM > MANY) & (WMC < VERY HIGH) ] }
  • FEW = 3 - 5
  • ONE THIRD = 0.33
  • WMC-HIGH-JAVA = 31
  • WMC-VERY HIGH-JAVA = 47
  • MANY = 7 (according to Sebastian Jancke)

Data Class in jd.plugins.FilePackageInfo (Jdownloader)

WOC #functional Methods #public members
Expected 0,11111 1 public constructor + 9 public methods + 0 public attributes(default is package ≠ public) == 10
Actual 0,11111 1 10
WOC NOPA NOAM WMC
Expected 0,11111 0 8 26
Actual 0,11111 0 8 26
WOC WOC < ONE THRID NOPA + NOAM NOPA + NOAM > FEW NOPA + NOAM > MANY WMC WMC < 31 WMC < 47 SMELL
Expected 0,11111 YES 8 YES YES 26 YES YES YES
Actual 0,11111 YES 8 YES YES 26 YES YES YES

Brain Method <definition!=implementation>

MetricsLines Of CodeCYCLOMaximum Depth Of NestingNumber Of Accessed Variables
  • Definition: Brain Method
    • Lines of Code > HIGH(Class)/2 ( for Java High Loc/Class == 130/2 (OOSMiP S. 16)) == 65
    • & CYCLO ≥ HIGH (for CYCLO/Method a.k.a. Average Method Weight) == 3.1
    • & Maximum depth of nesting ≥ Several == 5 (OOSMiP S. 18)
    • & Number Of Accessed Variables > MANY (more than a human can keep in short-term memory) == 7

Brain Method in bluej.Config.initialise(File, Properties)

The content of methods being defined whilst being an attribute are ignored! The implementation differs from the detection strategies in the book. In the book, a brainmethod exists, if the lines of code exceed the amount of Loc_class(high)/2 == 65. The implemented threshold is 43.

Lines Of Code
Expected 48
Actual 48
CYCLO
Expected 7
Actual 7
Maximum Depth Of Nesting
Expected 2
Actual 2
Number Of Accessed Variables
Expected 27 ⇒ bluejLibDir, bootingGreenfoot, commandProps, compilertype, debugLogName, greenfootDebugLogName, greenfootLibDir, greenfootProps, homeDir, initialCommandLineProps, initialised, isDebugVm, isGreenfoot, laf, langProps, language, macOSscreenMenuBar, moeSystemProps, moeUserProps, screenBounds, systemProps, tempCommandLineProps, themed, userHome, userPrefDir, userProps, usingMacOSScreenMenubar
Actual 27
LOC LOC > High(Class)/2 CYCLO CYCLO ≥ HIGH MAXNESTING MAXNESTING ≥ SEVERAL NOAV NOAV > MANY Smell
Expected 48 NO 7 Yes 2 YES 27 YES NO
Actual 48 YES 7 Yes 2 YES 27 YES YES

Feature Envy <has bugs>

Metrics ATFD LAA FDP
  • Definition: Feature Envy = (ATFD > FEW) & (LAA < ONE THIRD) & (FDP >= FEW)
  • FEW = 3 - 5, ONE THIRD = 0.33

Feature Envy in ShapeList.replaceShape

Accessed Foreign Data
Expected Shape.canvas, Shape.reporter, Shape.polylines
Actual Shape.canvas, Shape.reporter, Shape.polylines
Accessed Local Attributes
Expected own.shapes
Actual own.shapes
Foreign Data Provider
Expected Shape
Actual Shape
ATFD ATFD > FEW LAA LAA < ONE THIRD FDP FDP =< FEW SMELL
Expected 3 Yes 0.25 Yes 1 Yes Yes
Actual 3 Yes 0.25 Yes 1 Yes Yes
  • Currently shape is only counted in LAA if made private. It would be consistent with ATFD to consider inherited attributes as well and therefore as well protected and therefore as well package-visible attributes.

Feature Envy in RelocatableCup.relocate

Accessed Foreign Data
Expected PolyLine.vertices-size, PolyLine.vertices, Vertex.x, Vertex.y
Actual Vertex.x, Vertex.y
Accessed Local Attributes
Expected inherited.polylines
Actual inherited.polylines
Foreign Data Provider
Expected PolyLine, Vertex
Actual Vertex
ATFD ATFD > FEW LAA LAA < ONE THIRD FDP FDP =< FEW SMELL
Expected 4 Yes 0.2 Yes 2 Yes Yes
Actual 2 No 0.33 No 1 Yes No

God Class <discuss ATFD>

MetricsAccess to Foreign DataWeighted Method CountTight Class Cohesion
  • Definition: God Class
    • Access to Foreign Data > FEW == 4
    • & Weighted Method Count >= VERY HIGH (in Java 47)
    • & Tight Class Cohesion < 1/3

God Class in org.jaxen.expr.DefaultNameStep

Triviality of getter-methods given in all cases. “contextNodeSet.size” is an interface method, tough it's not possible to evaluate the complexity of the implementation as there are many objects possible while the app is running. Same with “contextNodeSet.get(0). According to the “normal” implementation of a List, the mentioned methods should be trivial getters.

Definition of ATFD: Only direct accesses and accesses via accessor are counted. contextNodeSet in this case might not count for ATFD. The value 3 seams to be right.

Access to Foreign Data
Expected context.getNodeSet(), contextNodeSet.size(), context.getContextSupport(), contextNodeSet.get(0)
Expected context.getNodeSet(), contextNodeSet.size() [== nodeSet], context.getContextSupport(), contextNodeSet.get(0) [== nodeSet], makes 2 attributes
Actual 3
Weighted Method Count
Expected 49
Actual 49
Tight Class Cohesion
Expected ??
Actual 0.1666666
ATFD ATFD > FEW WMC WMC ≥ VERY HIGH TCC TCC < 1/3 Smell
Expected 4 Yes 49 Yes ?? ??
Actual 3 Yes 49 Yes 0.16666 Yes Yes

Brain Class <find smallest brainclass & then check TCC>

Short Name
LOC Lines of Code
WMC Weighted Method Count
TCC Tight Class Cohesion
  • Definition: { (Several Brain Methods in very large class) OR (One Brain Method in extremely large class) } & (Very complex and non-cohesive Class)
  • Several Brain Methods in very large class
    • ( Class contains more than one Brain Method )
    • & ( LOC >= VERY HIGH )
  • One Brain Method in extremely large class
    • ( Class contains only one Brain Method )
    • &( LOC >= 2 * VERY HIGH )
    • & ( WMC >= 2 * VERY HIGH )
  • Very complex and non-cohesive Class
    • ( WMC >= VERY HIGH )
    • &( TCC < HALF )
  • LOC VERY HIGH = 195,FEW = 3 - 5, ONE THIRD = 0.33, HALF = 0.5 WMC VERY HIGH = 47

WMC does not count the complexity of an inner-synchronized “if”. For the following example cultivate measures a method-complexity of 2 which should be 3. The Method itself + first if + second if in the synchronized block.

JN + BH: Jan will fix this metric.

The TCC metric is too complex to be checked within a brainclass as the amount of attributes is usually very high. The implementation is equivalent to the definition of Bieman et al. in the following article: J. M. Bieman and B. K. Kang. Cohesion and reuse in an object-oriented system. In “Proceedings ACM Symposium on Software Reusability”, April 1995.

LOC (NOS)
Expected 319 excluding the import, package and the inner class section (including: 349)
Actual 359
WMC
Expected 187 (did not count try{}catch which exist 16 times in the measured class)
Actual 192
TCC
Expected ??
Actual 0.02151151722
LOC LOC ≥ VERY HIGH LOC ≥ 2 * VERY HIGH WMC WMC ≥ VERY HIGH WMC ≥ 2 * VERY HIGH TCC TCC < HALF SMELL
Expected 347 YES NO ?? ?? ?? ?? ??
Actual 359 YES NO 192 YES YES 0.02151151722 NO

Collaboration Disharmonies

Shotgun Surgery <Daniel will fix CC>

MetricsChanging MethodsChanging Classes
  • Definition: Shogun Surgery
    • Changing Methods > Short Memory Cap < 7
    • & Changing Classes > MANY

Shotgun Surgery in bluej.Config.isMacOS()

Changing Methods
Expected 21 FindPanel.addDisplayElement, DialogManager.adOKCancelButtons, ReplacePanel.addReplaceBody, Utility.bringToFront(Window), Utility changeToMacButton(AbstractButton), MoeEditor.createToolbarButton(String), Config.getBlueJPrefDirName, PackageFileView.getIcon(File), Info.info, PrefMrg.initEditorFontSize(int), Config.initialise(File, Properties, boolean), SelectionController.isMultiselectionKeyDown(MouseEvent), MoeActions.load, VMReference.localhostSocketLaunch(File, DebuggerTerminal, VirtualMachineManager), Utility.openWebBrowser(URL), PkgMgrAction.PkgMgrAction(String), ObjectInspector.run (2x), FindPanel.setPrevNextDisplay, TeamAction.TeamAction(String, boolean)
Actual 21
Changing Classes
Expected 17 FindPanel, DialogManager, ReplacePanel, Utility, MoeEditor, NaviviewView, BlueJTheme, Config, PackageFileView, Info, PrefMgr, SelectionController, MoeActions, VMReference, PkgMgrAction, ActionInspector, TeamAction
Actual 16
CM CM > Short Memory Cap CC CC > MANY Smell
Expected 21 Yes 17 Yes Yes
Actual 21 Yes 16 Yes Yes

Intensive Coupling <Discuss Maxnesting>

Metrics

Short Name
CINT Coupling Intensity
CDISP Coupling Dispersion
MAXNESTING Maximum Depth of Nesting
  • Definition: ( MAXNESTING > SHALLLOW ) & { [ (CINT > 7) & (CDISP < 1/2) ] OR [ (CINT > FEW) & (CDISP < 1/4) ] }
  • SHALLOW = 1
  • FEW = 3

Intensive Coupling in util.AssociativeMap.containsValue (QuickUML-2001)

Getting two values for CDISP.

MAXNESTING CINT CDISP
Expected 2 3 1/3
Actual 2 3 0
MAXNESTING MAXNESTING > SHALLOW CINT CINT > 7 CINT > FEW CDISP CDISP < 1/2 CDISP < 1/4 SMELL
Expected 2 YES 3 NO YES 1/3 YES NO NO
Actual 2 YES 3 NO YES 0 YES YES YES

Intensive Coupling in uml.ui.ScaledPrintableAction.print (QuickUML-2001)

MAXNESTING CINT CDISP
Expected 1 15 5/15 = 1/3
Actual 1 15 1/3

Maxnesting is not part of Cultivate's detection strategy for intensive coupling. See Daniel Speicher, “Evolving Software Quality Knowledge” https://sewiki.iai.uni-bonn.de/private/daniel/public/start, 2011 for reasons.

MAXNESTING MAXNESTING > SHALLOW CINT CINT > 7 CINT > FEW CDISP CDISP < 1/2 CDISP < 1/4 SMELL
Expected 1 NO(equal) 15 YES YES 1/3 YES NO NO
Actual 1 NO(equal) 15 YES YES 1/3 YES NO NO

Dispersed Coupling

Metrics CINT CDISP MAXNESTING
  • Definition: Dispersed Coupling = ( (CINT > Short Memory Cap) & (CDISP >= HALF) ) & (MAXNESTING > SHALLOW)
  • Short Memory Cap = 7, HALF = 0.5, SHALLOW = 1
Distinct operations called
Expected Window.addWindowListener+pack+setVisible, JFrame.getContentPane, Container.setLayout+add, ShapeList.getInstance+addShape, RelocatableCup.relocate, Math.random, RelocatableSmoke.relocate, System.exit (???)
Actual Window.addWindowListener+pack+setVisible, JFrame.getContentPane, Container.setLayout+add, ShapeList.getInstance+addShape, RelocatableCup.relocate, Math.random, RelocatableSmoke.relocate
Defining Classes
Expected Window (???), JFrame, Container, ShapeList, RelocatableCup, Math, RelocatableSmoke, System.exit (???)
Actual Window, JFrame, Container, ShapeList, RelocatableCup, Math, RelocatableSmoke
CINT CINT > SMC CDISP CDISP >= HALF MAXNESTING MAXNESTING > SHALLOW Smell
Expected 11 (12 ???) Yes 7 / 11 (7+1-1 / 12 ???) Yes 1 (3 ???) No (Yes ???) No
Actual 11 Yes 7 /11 Yes 1 No Yes
Remarks
  • JFrame inherits the methods from Window and the class Windows is nowhere explicitly referenced. Therefore is would be natural to not distinguish between JFrame and Window.
  • The nesting created by anonymous classes is impeding the understanding. But including it in the MAXNESTING metric immediately breaks the heuristic for configuration methods (MAXNESTING > SHALLOW).
  • Although the calls from within the method in the anonymous class are not executed as part of the main method itself, it would be natural to consider them as coupling of the main method as well.

Dispersed Coupling in uml.builder.CPlusBuilder.writeSourceConstructor (QuickUML-2001)

Distinct operations called
Expected MetaComponent.getName, MetaParameter.toString, PrintWriter.print&&.println, MetaMethod.hasExceptions, MetaException.toString, MetaConstructor.getAssociations&&.getParameters&&.getCompositions, Iterator.hasNext&&.next, MetaAttribute.getType
Actual _
Defining Classes
Expected MetaComponent, MetaParameter, PrintWriter, MetaMethod, MetaException, MetaConstructor, Iterator, MetaAttribute
Actual _
CINT CINT > SMC CDISP CDISP >= HALF MAXNESTING MAXNESTING > SHALLOW Smell
Expected 12 Yes 8/12 = 0,66666666 Yes 2 Yes Yes
Actual 12 Yes 0,66666666 Yes 2 Yes Yes

Classification Disharmonies

Tradition Breaker <has bugs>

Metrics

Short Name
NAS Number of Added Services
PNAS Percentage of Added Services
AMW Average Method Weight
WMC Weighted Method Count
NOM Number of Methods
  • Definition: {Child class increases it's interface excessively} & {Size and complexity of child class are not to low} && {Superclass is not too trivial}
  • {Child class increases it's interface excessively}
    • (NAS ≥ Average) & (PNAS ≥ 2/3)
  • {Size and complexity of child class are not to low}
    • { (AMW > Average) OR (WMC ≥ VERY HIGH) } & (NOM ≥ HIGH)
  • {Superclass is not too trivial}
    • (AMW(Superclass) > AVERAGE) & (NOM > HIGH) & (WMC ≥ VERY HIGH/2)
  • AVERAGE(NAS) = 6.5 (OOMIP p. 154)
  • AVERAGE(AMW) = 2.0 (OOMIP p. 16)
  • VERY HIGH(WMC) = 47(OOMIP p. 16)
  • HIGH(NOM) = 10 (OOMIP p. 16)

Tradition Breaker in jd.plugins.LinkGrabberFilePackage (jDownloader)

Superclass: Property

AMW has a problem with “synchronized”! PNAS isn't that precise! WMC might has a problem with “synchronized” as well!

NAS PNAS AMW WMC NOM (SC)AMW (SC)NOM (SC)WMC
Expected 45 0.977777777 2,0444444444 92 46 2 18 35
Actual 45 1 1.5652173913 72 46 2,22222222 18 40
NAS≥AVERAGE PNAS≥2/3 AMW>AVERAGE WMC≥VERY HIGH NOM≥HIGH
Expected YES YES YES YES YES
Actual YES YES NO YES YES
(SC)AMW>AVERAGE (SC)NOM>HIGH/2 (SC)WMC≥VERYHIGH/2 SMELL
Expected NO YES YES NO
Actual YES YES YES YES
  • AVERAGE(NAS) = 6.5 (OOMIP p. 154)
  • AVERAGE(AMW) = 2.0 (OOMIP p. 16)
  • VERY HIGH(WMC) = 47(OOMIP p. 16)
  • HIGH(NOM) = 10 (OOMIP p. 16)

Tradition Breaker in CH.ifa.draw.figures.LineConnection (JHotDraw 5.1)

NAS counts every method no matter if the method is an overriding method oder a newly added service. See example for proof:

NAS PNAS
Expected 3 0,103448275
Actual 19 0.6551724137931034

Refused Parent Bequest <has bugs>

Metrics

Short Name
NProtM Number of Protected Members
BUR Base Class Usage Ratio
BOvR Base Class Overriding Ratio
AMW Average Method Weight
WMC Weighted Method Count
NOM Number of Methods
  • Definition: {Child class ignores bequest} & {Child class is not too small and simple}
  • {Child class ignores bequest}
    • { (NProtM > FEW) & (BUR < 1/3) } OR (BOvR < 1/3)
  • {Child class is not too small and simple}
    • { (AMW > AVERAGE) OR (WMV > AVERAGE) } & (NOM > AVERAGE)
  • FEW = 3 - 5
  • ONE THIRD = 0.33
  • WMC-HIGH-JAVA = 31
  • WMC-VERY HIGH-JAVA = 47
  • MANY = 7 (according to Sebastian Jancke)

Refused Parent Bequest in jd.gui.swing.jdgui.views.downloads.columns.LoadedColumn (jDownloader)

WMC and AMW have a problem with synchronize!

NProtM BUR BOvR AMW WMC NOM
Expected 0 0 0.1 2 18 9
Actual 0 0 0.1 1,6666 15 9
NProtM NProtM > FEW BUR BUR < 1/3 BOvR BOvR < 1/3 AMW AMW> AVERAGE WMC WMC > AVERAGE NOM NOM > AVERAGE Smell
Expected 0 NO 0 YES 0.1 YES 2 NO 18 YES 9 YES YES
Actual 0 NO 0 YES 0.1 YES 1,6666 NO 15 YES 9 YES YES
  • AVERAGE(AMW) = 2
  • AVERAGE(WMC) = 14
  • AVERAGE(NOM) = 7

Other

Law of Demeter <EXAMPLES?>

Law of Demeter Violation in org.jaxen.baseXPath.setVariableContext(VariableContext variableContext) (Jaxen)

The variable accessed via the called method “setVariableContext” on the return type of “getContextSupport” is a variable, which is out of the class' demeter. A Law of Demeter Violation is present.

    // [...]

    /** Set a <Code>VariableContext

for use with this XPath

  • expression.
  • <p>
  • A
    VariableContext

    is responsible for resolving

  • all variables referenced within the expression.
  • </p>
  • @param variableContext The
    VariableContext

    to

  • install for this expression
  • @see VariableContext
  • @see VariableContext#getVariableValue
  • /

public void setVariableContext(VariableContext variableContext)

  {
      getContextSupport().setVariableContext(variableContext);
  }
  //[...]

</Code>

research/cultivate/start/smell_check.txt · Last modified: 2018/05/09 01:59 (external edit)

SEWiki, © 2019