Skip to content

Commit

Permalink
Change DependencyPairSet to DependencyMap
Browse files Browse the repository at this point in the history
  • Loading branch information
mihaeu committed Sep 13, 2016
1 parent 64aeb25 commit 9d15e2e
Show file tree
Hide file tree
Showing 23 changed files with 443 additions and 255 deletions.
6 changes: 3 additions & 3 deletions src/Analyser/Analyser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Mihaeu\PhpDependencies\Analyser;

use Mihaeu\PhpDependencies\Dependencies\DependencyPairSet;
use Mihaeu\PhpDependencies\Dependencies\DependencyMap;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\NameResolver;

Expand Down Expand Up @@ -32,9 +32,9 @@ public function __construct(NodeTraverser $nodeTraverser, DependencyInspectionVi
/**
* @param Ast $ast
*
* @return DependencyPairSet
* @return DependencyMap
*/
public function analyse(Ast $ast) : DependencyPairSet
public function analyse(Ast $ast) : DependencyMap
{
$ast->each(function (array $nodes) {
$this->nodeTraverser->traverse($nodes);
Expand Down
65 changes: 22 additions & 43 deletions src/Analyser/DependencyInspectionVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
use Mihaeu\PhpDependencies\Dependencies\Clazz;
use Mihaeu\PhpDependencies\Dependencies\DependencyFactory;
use Mihaeu\PhpDependencies\Dependencies\DependencyPair;
use Mihaeu\PhpDependencies\Dependencies\DependencyPairSet;
use Mihaeu\PhpDependencies\Dependencies\DependencyMap;
use Mihaeu\PhpDependencies\Dependencies\DependencySet;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall as MethodCallNode;
use PhpParser\Node\Expr\StaticCall as StaticCallNode;
Expand All @@ -25,18 +26,15 @@

class DependencyInspectionVisitor extends NodeVisitorAbstract
{
/** @var DependencyPairSet */
/** @var DependencyMap */
private $dependencies;

/** @var DependencyPair */
/** @var DependencySet */
private $tempDependencies;

/** @var Clazz */
private $currentClass;

/** @var Clazz */
private $temporaryClass;

/** @var DependencyFactory */
private $dependencyFactory;

Expand All @@ -46,28 +44,8 @@ class DependencyInspectionVisitor extends NodeVisitorAbstract
public function __construct(DependencyFactory $dependencyFactory)
{
$this->dependencyFactory = $dependencyFactory;

$this->dependencies = new DependencyPairSet();

$this->temporaryClass = $dependencyFactory->createClazzFromStringArray(['temporary class']);
$this->tempDependencies = new DependencyPair($this->temporaryClass);
}

/**
* This is called before any actual work is being done. The order in which
* the file will be traversed is not always as expected. We therefore
* might encounter a dependency before we actually know which class we are
* in. To get around this issue we will set the current node to temp
* and will update it later when we are done with the class.
*
* @param Node[] $nodes
*
* @return null|\PhpParser\Node[]|void
*/
public function beforeTraverse(array $nodes)
{
$this->currentClass = $this->temporaryClass;
return null;
$this->dependencies = new DependencyMap();
$this->tempDependencies = new DependencySet();
}

/**
Expand Down Expand Up @@ -123,26 +101,27 @@ public function leaveNode(Node $node)
{
if ($node instanceof ClassLikeNode) {
// not in class context
if ($this->currentClass->equals($this->temporaryClass)) {
$this->tempDependencies = new DependencyPair($this->temporaryClass);
if ($this->currentClass === null) {
$this->tempDependencies = new DependencySet();
return;
}

// by now the class should have been parsed so replace the
// temporary class with the parsed class name
$this->dependencies = $this->dependencies->add(new DependencyPair(
$this->dependencies = $this->dependencies->addSet(
$this->currentClass,
$this->tempDependencies->to()
));
$this->tempDependencies = new DependencyPair($this->temporaryClass);
$this->tempDependencies
);
$this->tempDependencies = new DependencySet();
$this->currentClass = null;
}
return null;
}

/**
* @return DependencyPairSet
* @return DependencyMap
*/
public function dependencies() : DependencyPairSet
public function dependencies() : DependencyMap
{
return $this->dependencies;
}
Expand Down Expand Up @@ -175,7 +154,7 @@ private function addParentDependency(ClassLikeNode $node)
? $node->extends
: [$node->extends];
foreach ($extendedClasses as $extendedClass) {
$this->tempDependencies = $this->tempDependencies->addDependency(
$this->tempDependencies = $this->tempDependencies->add(
$this->dependencyFactory->createClazzFromStringArray($extendedClass->parts)
);
}
Expand All @@ -187,7 +166,7 @@ private function addParentDependency(ClassLikeNode $node)
private function addImplementedInterfaceDependency(ClassNode $node)
{
foreach ($node->implements as $interfaceNode) {
$this->tempDependencies = $this->tempDependencies->addDependency(
$this->tempDependencies = $this->tempDependencies->add(
$this->dependencyFactory->createClazzFromStringArray($interfaceNode->parts)
);
}
Expand All @@ -198,7 +177,7 @@ private function addImplementedInterfaceDependency(ClassNode $node)
*/
private function addInstantiationDependency(NewNode $node)
{
$this->tempDependencies = $this->tempDependencies->addDependency(
$this->tempDependencies = $this->tempDependencies->add(
$this->dependencyFactory->createClazzFromStringArray($node->class->parts)
);
}
Expand All @@ -211,7 +190,7 @@ private function addInjectedDependencies(ClassMethodNode $node)
foreach ($node->params as $param) {
/* @var \PhpParser\Node\Param */
if (isset($param->type, $param->type->parts)) {
$this->tempDependencies = $this->tempDependencies->addDependency(
$this->tempDependencies = $this->tempDependencies->add(
$this->dependencyFactory->createClazzFromStringArray($param->type->parts)
);
}
Expand All @@ -223,7 +202,7 @@ private function addInjectedDependencies(ClassMethodNode $node)
*/
private function addUseDependency(UseNode $node)
{
$this->tempDependencies = $this->tempDependencies->addDependency(
$this->tempDependencies = $this->tempDependencies->add(
$this->dependencyFactory->createClazzFromStringArray($node->uses[0]->name->parts)
);
}
Expand All @@ -233,7 +212,7 @@ private function addUseDependency(UseNode $node)
*/
private function addStaticDependency(MethodCallNode $node)
{
$this->tempDependencies = $this->tempDependencies->addDependency(
$this->tempDependencies = $this->tempDependencies->add(
$this->dependencyFactory->createClazzFromStringArray($node->var->class->parts)
);
}
Expand All @@ -254,7 +233,7 @@ private function isSubclass(ClassLikeNode $node)
private function addUseTraitDependency(Node $node)
{
foreach ($node->traits as $trait) {
$this->tempDependencies = $this->tempDependencies->addDependency(
$this->tempDependencies = $this->tempDependencies->add(
$this->dependencyFactory->createTraitFromStringArray($trait->parts)
);
}
Expand Down
95 changes: 42 additions & 53 deletions src/Analyser/Metrics.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,117 +8,106 @@
use Mihaeu\PhpDependencies\Dependencies\Clazz;
use Mihaeu\PhpDependencies\Dependencies\Dependency;
use Mihaeu\PhpDependencies\Dependencies\DependencyPair;
use Mihaeu\PhpDependencies\Dependencies\DependencyPairSet;
use Mihaeu\PhpDependencies\Dependencies\DependencyMap;
use Mihaeu\PhpDependencies\Dependencies\DependencySet;
use Mihaeu\PhpDependencies\Dependencies\Interfaze;
use Mihaeu\PhpDependencies\Dependencies\Trait_;

class Metrics
{
/**
* @param DependencyPairSet $dependencies
* @param DependencyMap $map
*
* @return float Value from 0 (completely concrete) to 1 (completely abstract)
*/
public function abstractness(DependencyPairSet $dependencies) : float
public function abstractness(DependencyMap $map) : float
{
$abstractions = $this->abstractClassCount($dependencies)
+ $this->interfaceCount($dependencies)
+ $this->traitCount($dependencies);
$allClasses = $this->classCount($dependencies)
+ $this->abstractClassCount($dependencies)
+ $this->interfaceCount($dependencies)
+ $this->traitCount($dependencies);
$abstractions = $this->abstractClassCount($map)
+ $this->interfaceCount($map)
+ $this->traitCount($map);
$allClasses = $this->classCount($map)
+ $this->abstractClassCount($map)
+ $this->interfaceCount($map)
+ $this->traitCount($map);
return $abstractions / $allClasses;
}

public function classCount(DependencyPairSet $dependencies) : int
public function classCount(DependencyMap $map) : int
{
return $this->countFilteredItems($dependencies, function (Dependency $dependency) {
return $this->countFilteredItems($map, function (Dependency $dependency) {
return $dependency instanceof Clazz;
});
}

public function abstractClassCount(DependencyPairSet $dependencies) : int
public function abstractClassCount(DependencyMap $map) : int
{
return $this->countFilteredItems($dependencies, function (Dependency $dependency) {
return $this->countFilteredItems($map, function (Dependency $dependency) {
return $dependency instanceof AbstractClazz;
});
}

public function interfaceCount(DependencyPairSet $dependencies) : int
public function interfaceCount(DependencyMap $map) : int
{
return $this->countFilteredItems($dependencies, function (Dependency $dependency) {
return $this->countFilteredItems($map, function (Dependency $dependency) {
return $dependency instanceof Interfaze;
});
}

public function traitCount(DependencyPairSet $dependencies) : int
public function traitCount(DependencyMap $map) : int
{
return $this->countFilteredItems($dependencies, function (Dependency $dependency) {
return $this->countFilteredItems($map, function (Dependency $dependency) {
return $dependency instanceof Trait_;
});
}

/**
* Afferent coupling is an indicator for the responsibility of a package.
*
* @param DependencyPairSet $dependencies
* @param DependencyMap $map
*
* @return array
*/
public function afferentCoupling(DependencyPairSet $dependencies) : array
public function afferentCoupling(DependencyMap $map) : array
{
$afferent = [];
foreach ($dependencies->fromDependencies()->toArray() as $dependencyFrom) {
/** @var Dependency $dependencyFrom */
$afferent[$dependencyFrom->toString()] = 0;
foreach ($dependencies->toArray() as $dependencyPair) {
/** @var DependencyPair $dependencyPair */
if ($dependencyPair->to()->any(function (Dependency $dependency) use ($dependencyFrom) {
return $dependency->equals($dependencyFrom);
return $map->reduce([], function (array $afferent, DependencySet $to, Dependency $from) use ($map) {
$afferent[$from->toString()] = 0;
return $map->reduce($afferent, function (array $afferent, DependencySet $to, Dependency $fromOther) use ($from) {
if ($to->any(function (Dependency $dependency) use ($from) {
return $dependency->equals($from);
})) {
++$afferent[$dependencyFrom->toString()];
++$afferent[$from->toString()];
}
}
}
return $afferent;
return $afferent;
});
});
}

/**
* Efferent coupling is an indicator for how independent a package is.
*
* @param DependencyPairSet $dependencies
* @param DependencyMap $map
*
* @return array
*/
public function efferentCoupling(DependencyPairSet $dependencies) : array
public function efferentCoupling(DependencyMap $map) : array
{
$efferent = [];
foreach ($dependencies->fromDependencies()->toArray() as $dependencyFrom) {
/** @var Dependency $dependencyFrom */
$efferent[$dependencyFrom->toString()] = 0;
foreach ($dependencies->toArray() as $dependencyPair) {
/** @var DependencyPair $dependencyPair */
if ($dependencyPair->from()->equals($dependencyFrom)
) {
++$efferent[$dependencyFrom->toString()];
}
}
}
return $efferent;
return $map->reduce([], function (array $efferent, DependencySet $to, Dependency $from) {
$efferent[$from->toString()] = $to->count();
return $efferent;
});
}

/**
* Instability is an indicator for how resilient a package is towards change.
*
* @param DependencyPairSet $dependencyPairCollection
* @param DependencyMap $map
*
* @return array Key: Class Value: Range from 0 (completely stable) to 1 (completely unstable)
*/
public function instability(DependencyPairSet $dependencyPairCollection) : array
public function instability(DependencyMap $map) : array
{
$ce = $this->efferentCoupling($dependencyPairCollection);
$ca = $this->afferentCoupling($dependencyPairCollection);
$ce = $this->efferentCoupling($map);
$ca = $this->afferentCoupling($map);
$instability = [];
foreach ($ce as $class => $count) {
$totalCoupling = $ce[$class] + $ca[$class];
Expand All @@ -129,8 +118,8 @@ public function instability(DependencyPairSet $dependencyPairCollection) : array
return $instability;
}

private function countFilteredItems(DependencyPairSet $dependencyPairCollection, \Closure $closure)
private function countFilteredItems(DependencyMap $map, \Closure $closure)
{
return $dependencyPairCollection->fromDependencies()->filter($closure)->count();
return $map->fromDependencies()->filter($closure)->count();
}
}

0 comments on commit 9d15e2e

Please sign in to comment.