Introducing Component Cohesion/Coupling Digraphs

DoubleX

Just a nameless weakling
Veteran
Joined
Jan 2, 2014
Messages
1,787
Reaction score
939
First Language
Chinese
Primarily Uses
N/A
This post aims to cover the basic knowledge on Component Cohesion/Coupling Digraphs(Com Coh/Cou Digraph, same below). Subsequent replies will demonstrate some practical applications in some plugins.


You're assumed to have a basic knowledge on:


1. Block diagram


2. Cohesion


3. Coupling


4. Digraphs


Component Diagram

Layered Approach



Spoiler



Let's start with the below easy, simple and small block diagram showing the high level of a system:



Spoiler




This system uses the Core Addon Approach - 1 plugin as the core that's essential for the system, and a number of plugins, each needing the core plugin to work, that are all optional for the system.


If we want to know the details of a plugin of a system, we can also use a block diagram for each plugin, which can be something like this:


If each feature's considered as a component, then this plugin's said to have 12 components(you may want to have a basic knowledge on interface in case you don't).


So as we go from a higher layer to a lower layer, more and more details of a component will be shown, but less and less information about how that component interact with the entire system as a whole will be revealed as well.




Showing Number Of Components

As mentioned, a system can have a number of plugins, a plugin can have a number of features, and a feature can have a number of building blocks. What levels of the details will be shown on a graph depends on the layer we're focusing on.


Sometimes though, the number of components within a system/plugin/feature can also be useful, like indicating whether a component's doing too much or too little.


Showcasing the number of components in a block diagram can be as simple as this:



Spoiler




Here Com: x indicates the number of components within a plugin. In this case, it's the number of features within a plugin.


So the core plugin has 9 features and each addon plugin has 3 - 4 features. The total number of features of the whole system is 51.


From my experience, knowledge and observation, these are pretty good numbers, because it's normal for the core plugin to do a lot more than each addon plugin, and no plugin's doing too much or too little.


Note that a block diagram on a layer only shows the number of components on 1 lower layer for each component on this layer. It's because of the Law of Demeter.


In short, this approach ensures the overview shown by a high level block diagram won't be obscured by the details from lower levels, except the one just lower than the current level.


In this case, Com only shows the number of feature in each plugin, but not the number of building blocks of each feature in each plugin.


To know the number of building blocks of each feature in each plugin, we can look at the block diagram of that plugin instead.


On a side note: While the number of subcomponents within a component can be an excellent approximation of the size of that component in general, it's never meant to be always accurate nor precise for that sense. It's because sometimes a subcomponent can be exceptionally large or small.










Cohesion Diagram

Cohesion Rating(Coh Rating, Same Below)



Spoiler



Let's recap different kinds of cohesion. According to wikipedia, the below are all kinds of cohesions that are ordered by the best to the worst:


1. Functional cohesion


2. Sequential cohesion


3. Communicational cohesion


4. Procedural cohesion


5. Temporal cohesion


6. Logical cohesion


7. Coincidental cohesion


If we were to use a number as a rating to represent the cohesion level of a component, we can simply use the above numbers - 1 represents functional cohesion, 2 represents sequential cohesion, 3 represents communicational cohesion, ..., 7 represents coincidental cohesion.


That's what's Coh Rating's about. The smaller the number, the higher the cohesion. Note that it's a simplified indicator that gives a quick, rouge and vague impression of how good the cohesion of a component is.

Showing Coh Rating Of A Component

Just like showing the number of components in a block diagram, showing the Coh Rating in a block diagram can be as simple as this:



Spoiler




Here Coh: x indicates the Coh Rating of a plugin.


So the core plugin exhibits sequential cohesion and all addon plugins exhibit functional cohesion. The Coh Rating Sum of the whole system's 14.


From my experience, knowledge and observation, these are pretty good numbers, because functional cohesion's ideal and sequential cohesion's still acceptable.


Note that a block diagram on a layer only shows the Coh Rating of components on this layer. The reason behind that's basically the same as those of the number of components(Com: x).


In this case, Coh: x of a plugin only indicates the overall Coh Rating of that plugin, but not that of any feature within that plugin.


On a side note: The overall Coh Rating of the entire system can be different from that derived from diving its Cohesion Rating Sum(Coh Rating Sum, same below) by its number of components. Nevertheless, these 2 numbers are extremely unlikely to have a huge difference.










Coupling Digraph

Coupling Rating(Cou Rating, Same Below)



Spoiler



Let's recap different kinds of coupling. According to wikipedia, the below are all kinds of couplings that are ordered by the best to the worst:


0. No coupling


1. Message coupling


2. Data coupling


3. Stamp coupling


4. Control coupling


5. External coupling


6. Common coupling


7. Content coupling


If we were to use a number as a rating to represent the coupling level of between components, we can simply use the above numbers - 1 represents message coupling, 2 represents data coupling, 3 represents stamp coupling, ..., 7 represents content coupling.


That's what's Cou Rating's about. The smaller the number, the looser the coupling. Note that it's a simplified indicator that gives a quick, rouge and vague impression of how good the coupling between components are.


On a side note: Temporal coupling's not included here, as it's rather hard to give a rating for temporal coupling, and the key of temporal coupling's how implicit it's. Making a temporal coupling explicit can be simply done by excellent documentations.

Showing Cou Rating Between Components

Showing the Cou Rating between components is a bit more complicated, convoluted and costly when compared to that of the number of components and Coh Rating, but it should still be easy, simple and small:



Spoiler




Notice that this time arrows are used instead of merely simple lines, meaning that the block diagram's now a digraph.


If component A and component B are connected by an arrow which is pointing from component A to component B, then component A is said to depend on component B.


It's possible that they're connected by 2 arrows instead - 1 pointing from component A to component B and 1 having the opposite direction. In this case, these 2 components depend on each other.


Regardless of whether there are just 1 arrow or 2 arrows between these components, they're said to exhibit coupling when they're connected by at least 1 arrows.


Conversely, if component A and component B aren't connected by any arrows, they're said to exhibit no coupling.


Here Cou: x indicates the Cou Rating of a plugin. Note that a Cou Rating always has its corresponding arrow.


So the core plugin doesn't depend on any addon plugin while all addon plugins depend on the core plugin, all exhibiting message coupling/data coupling. The Coupling Rating Sum(Cou Rating Sum, same below) of the entire system's 18.


From my experience, knowledge and observation, these are pretty good numbers, because message coupling's ideal and data coupling's still acceptable and sometimes necessary.


Note that a block diagram on a layer only shows the Cou Rating between components on this layer. The reason behind that's basically the same as those of the number of components(Com: x) and Coh Rating(Coh: x).


In this case, Cou: x of a plugin only indicates the overall Cou Rating between plugins, but not that between features within any plugin or between plugins.


Bear in mind though, sometimes no coupling can be undesirable, as shown by the below block diagram:


Here addon plugin 4 exhibits no coupling to the rest of the system(i.e.:, the Cou Rating Sum of addon plugin 4 is 0), meaning that the former can function as intended without the latter at all.


In this case, addon plugin 4 doesn't really belong to the system and thus should be a completely separate plugin that can totally stand on its own instead.




InCou Rating/OutCou Rating

For components depending on each other, the block diagram may look something like this:



Spoiler




If Cou: x is attached to an arrow directing from component A to component B, then the InCou Rating of component B from component A's x, and the OutCou Rating of component A to component B's x.


The InCou Rating Sum of a component's the sum of all InCou Rating of that component; The OutCou Rating Sum of a component's the sum of all OutCou Rating of that component.


Looking at each addon plugin:


1. For the InCou Rating of addon plugin 1, it exhibits message coupling from addon plugin 2 and data coupling from addon plugin 3; For the OutCou Rating of addon plugin 1, it exhibits It exhibits data coupling to core plugin and addon plugin 2, and message coupling to addon plugin 3.


2. For the InCou Rating of addon plugin 2, it exhibits message coupling from addon plugin 3 and data coupling from addon plugin 1; For OutCou Rating of addon plugin 2, it exhibits It exhibits data coupling to core plugin and addon plugin 3, and message coupling to addon plugin 1.


3. For the InCou Rating of addon plugin 3, it exhibits message coupling from addon plugin 1 and data coupling from addon plugin 2; For OutCou Rating of addon plugin 3, it exhibits It exhibits data coupling to core plugin and addon plugin 1, and message coupling to addon plugin 2.


Note that The InCou Rating Sum of each addon plugin's 3 and its OutCou Rating Sum's 5.


In this case, it's somehow undesirable although still barely bearable, as changing any addon plugin can risk changing the rest of the addon plugins. Ideally, each addon plugin should never interfere any other plugin, and only depend on the core plugin and nothing else.


On a side note: The Cou Rating Sum of the entire system's 15.


In general:


1. The larger the InCou Rating Sum of a component, the easier and more severely that component will be broken due to changes of any other component it's depending on.


2. The larger the OutCou Rating Sum of a component, the easier and more severely that component will break at least some other components depending on it due to it changes.


3. If a component has large InCou Rating Sum and OutCou Rating Sum, when it becomes broken due to changes of some components it depends on, it can in turn break some components depending on it.










Com Coh/Cou Digraph

Putting Everything Altogether



Spoiler



While component diagram, cohesion diagram and coupling digraph are useful on their own, it's still better to combine them all in a single digraph. That's what Com Coh/Cou Digraph's about.


For example, combing all the above component diagram, cohesion diagram and coupling digraph can lead to this Com Coh/Cou Digraph:



Spoiler




So a Com Coh/Cou Digraph can quickly shows the below information of its layer entirely:


1. The number of subcomponents of each component


2. The total number of subcomponents


3. The Coh Rating of each component


4. The Coh Rating Sum


5. The directed dependencies between components


6. The InCou Rating of each component


7. The OutCou Rating of each component


8. The InCou Rating Sum of each component


9. The OutCou Rating Sum of each component


10. The Cou Rating Sum of this layer


These information can reveal the overview of the structural health of a component corresponding to this Com Coh/Cou Digraph, which is useful for preliminary diagnosis, albeit without a 100% guarantee.


For instance, the above Com Coh/Cou Digraph demonstrates a pretty decent system design, because all its information shown is quite good.


On a side note: If drawing a Com Coh/Cou Digraph for a system's rather difficult, then it can mean that the system itself's incredibly ill-designed.




Relations Between Com, Coh, InCou And OutCou

The point of combining component diagram, cohesion diagram and coupling digraph into a single Com Coh/Cou Digraph isn't just to show all useful information in 1 shot, but also to demonstrate the relationships between those information.


For instance, the below Com Coh/Cou Digraph illustrates this:



Spoiler




While it clearly and quickly demonstrates that the system has lots of structural health issues even when it seems to be easy, simple and small, let's still focus on each plugin 1 by 1:


1. Core plugin -


- As it exhibits communicational cohesion, which is generally considered to be a moderate code smell, the core plugin warrants detailed exploration, whether by using its own Com Coh/Cou Digraph or not.


- Compared to the total number of features of the whole system, which is 27, and the number of plugins in this system, which is 5, it's likely that the core plugin's still doing a bit too little.


- As the Coh Rating is a bit high when compared to the number of features, it can indicate that those features themselves are not well-defined enough, like some features overlapping too much with some others, or some features are simply wrapping up too many functionalities.


2. Addon plugin 1 -


- As it doesn't depend on the core plugin but rather another addon plugin, the depth of the system increases from 2 to 3, which complicates the system which is using the Core Addon Approach(the depth of such system should be always 2). It's because users must also activate another addon plugin in order to use this addon plugin.


- While it exhibits functional cohesion which is ideal, its number of components is also 1, meaning that this addon plugin's probably doing too little.


- As it exhibits content coupling with another plugin, which is generally considered to be 1 of the most destructive antipatterns, this plugin can break very easily and severely whenever addon plugin 4 changes. This can also lead to bugs that are actually due to this plugin even when they seem to stem from addon plugin 4.


- Combining all the above, it's likely that the entirety of this plugin should really be embedded as parts of addon plugin 4 instead, or the reverse - some features of addon plugin 4 should be placed on addon plugin 1, and the latter should depend on the core plugin instead of the former.


3. Addon plugin 2 -


- As it exhibits logical cohesion, which is generally considered to be a severe antipattern, it's likely that the features of this plugin doesn't really belong to the same plugin.


- As it only has 2 features while exhibiting logical cohesion, it's likely that the system designer isn't practicing system designs with excellent structural health. It's because normally the smaller number of components, the easier the cohesion to be higher.


- As it exhibits external coupling with another plugin, which is generally considered to be a moderate antipattern, it can mean that the features are probably not properly grouped or even well-defined, or addon plugin 4's simply an extremely ill-designed and implemented god object, especially when considering its high number of features, poor Coh Rating, and the high InCou Rating Sum.


4. Addon plugin 3 -


- As its number of features are 8 while it exhibits sequential cohesion which is still acceptable, this can either mean that those features are too small or the system's really covering a large number of features that are themselves tightly coupled, which can mean that those features are poorly defined.


- Nevertheless, it's probably the addon plugin with the best structural health.


5. Addon plugin 4 -


- It should be almost certain that this plugin's the one with the worst structural health, because it has the largest number of components which is clearly too large, the worst Coh Rating, the largest InCou Rating Sum and OutCou Rating Sum, and depends on and is depended on the largest number of plugins. It means that it's the addon plugin that should be dealt with first.


- It means that this addon's most likely an extremely ill-designed and implemented god object, which is already mentioned before.


- Combined with the fact that the core plugin's doing a bit too little, it's probable that some features of addon plugin 4 should belong to the core addon instead.


- Even then, addon plugin 4 will still likely be a big ball of mud, meaning that some of the rest of the features should be further delegated to some other existing of new addon plugins.


- Considering the fact that this plugin exhibits common coupling, which is generally considered to be a severe antipattern, with the core plugin, it seems that the this addon plugin affect so much of the system, as if it were the core plugin instead.


- Because of this plugin exhibiting control coupling, which is generally considered to be a severe code smell, to addon plugin 3, it looks like that the former's attempting to interfere with the latter. That's far from ideal in the Core Addon Approach, in which every addon plugin should never interfere with any other plugin, and only depend on and the core plugin and nothing else.


On a side note: The OutCou Rating Sum of the core addon should be 0, that of an addon plugin should be 1 or 2, and the InCou Rating Sum of an addon plugin should be 0.










Summary

Component Diagram



Spoiler



For a layered system, a block diagram can demonstrate the structural overview of a component on a certain layer. When it's the highest layer, the block diagram can demonstrate the structural overview of the entire system. Such diagrams will only expose details on its layer and the one immediately below it, like the number of subcomponents in a component shown by the block diagram.


So as we go from a higher layer to a lower layer, more and more details of a component will be shown, but less and less information about how that component interact with the entire system as a whole will be revealed as well.


In short, this approach ensures the overview shown by a high level block diagram won't be obscured by the details from lower levels, except the one just lower than the current level.

Cohesion Diagram

A cohesion diagram can show the Coh Rating, which is a simplified indicator of how high the cohesion is, of a component in a block diagram, and the Coh Rating Sum of the diagram, which is the sum of Coh Rating of all components in the diagram. The lower the Coh Rating and Coh Rating Sum, the higher the cohesion in general.


The overall Coh Rating of the entire system can be different from that derived from diving its Coh Rating Sum by its number of components. Nevertheless, these 2 numbers are extremely unlikely to have a huge difference.

Coupling Digraph

A coupling digraph can show the Cou Rating, which is a simplified indicator of how loose the coupling is, between components in a digraph, and the Cou Rating Sum of the digraph, which is the sum of Cou Rating of all components in the diagram. The lower the Cou Rating and Cou Rating Sum, the looser the coupling in general.


The InCou Rating of a component indicates the coupling from other component to that component; The OutCou Rating of a component indicates the coupling from that component to other components.


The InCou Coupling Sum of a component is the sum of all InCou Rating of that component; The OutCou Coupling Sum of a component is the sum of all OutCou Rating of that component.


In general:


1. The larger the InCou Rating Sum of a component, the easier and more severely that component will be broken due to changes of any other component it's depending on.


2. The larger the OutCou Rating Sum of a component, the easier and more severely that component will break at least some other components depending on it due to it changes.


3. If a component has large InCou Rating Sum and OutCou Rating Sum, when it becomes broken due to changes of some components it depends on, it can in turn break some components depending on it.


For a component having 0 Cou Rating Sum, it means that component doesn't really belong to the system and should become a completely separate plugin that can totally stand on its own.

Com Coh/Cou Digraph

A Com Coh/Cou Digraph, which is a combination of a component diagram, cohesion diagram and coupling digraph, can reveal the overview of the structural health of its corresponding component, which is useful for preliminary diagnosis, albeit without a 100% guarantee.


This is done by quickly showing all the useful information in 1 shot and demonstrating their relationships:


1. The number of subcomponents of each component


2. The total number of subcomponents


3. The Coh Rating of each component


4. The Coh Rating Sum


5. The directed dependencies between components


6. The InCou Rating of each component


7. The OutCou Rating of each component


8. The InCou Rating Sum of each component


9. The OutCou Rating Sum of each component


10. The Cou Rating Sum of this layer


For instance:


1. Normally the smaller number of components, the easier the cohesion to be higher.


2. Components having an exceptionally large/small number of subcomponents, having a poor Coh Rating, InCou Rating or OutCou Rating, or having an extraordinarily large InCou Rating Sum or OutCou Rating Sum, are most likely outstanding troublemakers and should thus be prioritized over those not as problematic.


If drawing a Com Coh/Cou Digraph for a system's rather difficult, then it can mean that the system itself's incredibly ill-designed.






That's all for now. As mentioned, I'll use some plugins to demonstrate some practical applications in the subsequent replies.
 
Last edited by a moderator:

DoubleX

Just a nameless weakling
Veteran
Joined
Jan 2, 2014
Messages
1,787
Reaction score
939
First Language
Chinese
Primarily Uses
N/A
Now I'll use DoubleX RMMV Minimalized ATB(MATB, same below) to demonstrate some practical applications of Com Coh/Cou Digraph.


Before I start, I want to emphasize that, while there are many ways to come up with a Com Coh/Cou Digraph, coming up with one accurately and precisely illustrating the system structure often needs one to at least have a basic knowledge on that system itself.


Therefore you're assumed to have a basic knowledge on writing ATB(Active Time Battle) system plugins.


Note that this reply will only show the top level of MATB, due to its bottom level being too tiny and trivial to be shown. It's because MATB's supposed to be a minimum viable product.


Top Level

System Structure



Spoiler



Recall that MATB consists of the following on the top level:


1. Battle Frame Update - Always run per frame(also handles action executions)


2. ATB Wait Condition - Checks if the ATB Frame Update can be run for the current Battle Frame Update


3. ATB Frame Update - Runs all battle flows unique to ATB systems


4. Battler ATB Clock - Controls the speed of each battler in ATB systems


5. Setup new Action Execution Subject - If there's none, setups the battler having completely inputted all actions to be the Action Execution Subject


6. Battle Turn Clock - Based on the number of ATB Frame Update passed to update the number of turns passed


7. Setup Inputable Actors - Lets players input commands for newly inputable actors


8. Status Window ATB Bars - Shows the Battler ATB Clock for each battler on the status window


And the flow is basically this:


1. If there's Action Execution Subject executing actions, the Battle Frame Update will handle those action executions


2. The Battle Frame Update will call the ATB Wait Condition to see if the ATB Frame Update can be run.


3. If the ATB Frame Update can be run, the Battler ATB Clock will be updated.


4. Then new Action Execution Subjects will be setup if there's none already but there are such eligible battlers


5. After that, the Battle Turn Clock will be updated to update the battle turn count


6. If there are actors becoming inputable, the actor command window will be setup for that actor


7. Finally the ATB bars that are shown on the status window will be updated

Com Coh/Cou Digraph

The below is a Com Coh/Cou Digraph illustrating the structural health for the top layer of MATB:



Spoiler




About the correctness of this Com Coh/Cou Digraph:

The Battle Frame Update has 2 components - 1 for executing actions for the Action Execution Subject, and 1 for calling ATB Frame Update when the ATB Wait Condition's met. It's shown in Scene_Battle.prototype.updateBattleProcess:



Spoiler







Scene_Battle.prototype.updateBattleProcess = function() { // Rewrite; Hotspot
// Rewritten to reconstruct the action input and execution flows for atb
if (BattleManager.isAborting() || BattleManager.isBattleEnd()) {
return BattleManager.update();
}
if (BattleManager.isBusy() || BattleManager.updateEvent()) { return; }
if (BattleManager.phase === 'action') return BattleManager.updateAction();
if (BattleManager.can_update_matb() && !this.isAnyInputWindowActive()) {
this.update_matb();
}
//
}; // Scene_Battle.prototype.updateBattleProcess

The Coh Rating of the Battle Frame Update is 1 - functional cohesion, as all it does is to run the battle flow per frame.


The OutCou Rating of the Battle Frame Update to the ATB Wait Condition and ATB Frame Update are both 1 - message coupling, as all the former needs are the latter's function names(BattleManager.can_update_matb, Scene_Battle.prototype.isAnyInputWindowActive and Scene_Battle.prototype.update_matb in this case).


The ATB Wait Condition has 2 components - 1 for checking whether the ATB Frame Update can be run(i.e., to prevent crashing the game), and 1 for checking whether the latter will be run(in this case it's whether plyaers are inputting commands). It's shown in Scene_Battle.prototype.updateBattleProcess which calls BattleManager.can_update_matb:

BattleManager.can_update_matb = function() { // New; Hotspot
return this._phase && this._phase !== 'init';
}; // BattleManager.can_update_matb

The Coh Rating of the ATB Wait Condition is 1 - functional cohesion, as all it does is to determine whether the ATB Frame Update will be run.


The ATB Frame Update has 2 components - 1 for running ATB flow focusing on data(in this case, the Battler ATB Clock, the Setup New Action Execution Subject and the Battle Turn Clock), and 1 for running ATB flow focusing on UI(in this case, the Setup Inputable Actors and Status Window ATB Bars). It's shown in Scene_Battle.prototype.update_matb and BattleManager.update_matb:

Scene_Battle.prototype.update_matb = function() { // New; Hotspot
BattleManager.update_matb();
var actor_indices = BattleManager.action_battlers.filter(function(battler) {
return battler.canInput();
}).map(function(battler) { return battler.index(); });
if (actor_indices.indexOf(this._statusWindow.index()) < 0) {
this.update_matb_actor_selection(actor_indices);
}
this._statusWindow.refresh_matb_bars();
}; // Scene_Battle.prototype.update_matb

Code:
BattleManager.update_matb = function() { // New; Hotspot
    $gameParty.aliveMembers().forEach(function(mem) { mem.update_matb(); });
    $gameTroop.aliveMembers().forEach(function(mem) { mem.update_matb(); });
    if (this._phase !== 'action') this.process_matb_turn();
    this.update_matb_turn();
}; // BattleManager.update_matb

The Coh Rating of the ATB Frame Update is 1 - functional cohesion, as all it does is to run the ATB flow(mechanics unique to ATB systems) per frame.


The OutCou Rating of the ATB Frame Update to the Battler ATB Clock is 3 - stamp coupling, as BattleManager isn't supposed to interact with battlers directly, but rather ask the game party/troop to deal with their own battlers with some specific commands. Now BattleManager.update_matb shows that BattleManager actually knows it has to call Game_Unit.prototype.aliveMembers and Game_Battler.prototype.update_matb, which are absolutely violations of the Law of Demeter.


The OutCou Rating of the ATB Frame Update to the Setup New Action Execution Subject and Battle Turn Clock are both 1 - message coupling, as all the former needs to know is the latters' function names(BattleManager.process_matb_turn and BattleManager.update_matb_turn in this case).


The OutCou Rating of the ATB Frame Update to the Setup Inputable Actors is 3 - stamp coupling, as Scene_Battle.prototype isn't supposed to know any details about BattleManager._actionBattlers, but rather ask BattleManager to deal with it with some specific commands. Now BattleManager exposes how BattleManager._actionBattlers is used, which is again a violation of the Law of Demeter.


The OutCou Rating of the ATB Frame Update to the Status Window ATB Bars is 1 - message coupling, as all the former needs to know is the latter's function name(Window_BattleStatus.prototype.refresh_matb_bars in this case).


The Battler ATB Clock has 4 components - Setting the starting ATB value, updating the ATB value(and making actions and marking battlers as Actable upon becoming having full ATB) , resetting itself(emptying the ATB value, clearing actions and marking battlers as Unactable) and confirming actions upon finishing inputting them. It's shown by the majority of Game_Action.prototype fuctions, Game_BattlerBase.prototype functions, Game_Battler.prototype functions and some Game_Actor.prototype functions(quoting them all here would include nearly half of the plugin implementations so you may want to check them yourselves instead).


The Coh Rating of the Battler ATB Clock is 1 - functional cohesion, as all it does is to control the speed of each battler in battle.


The Setup New Action Execution Subject has 2 components - Finding such eligible battlers and starting action executions for the new Action Execution Subject. It's shown by BattleManager.process_matb_turn:

BattleManager.process_matb_turn = function() { // New; Hotspot
this._subject = this._subject || this._actionBattlers.filter(function(b) {
return !b.can_input_matb();
})[0];
if (this._subject) this.processTurn();
}; // BattleManager.process_matb_turn

The Coh Rating of the Setup New Action Execution Subject is 1 - functional cohesion, as all it does is to setup a new Action Execution Subject from such eligible battlers.


The OutCou Rating of the Setup New Action Execution Subject to Battler ATB Clock is 1 - message coupling, as all the former needs to know is the latter's function names(Game_Battler.prototype.can_input_matb in this case) and the use of BattleManager._actionBattlers.


The Battle Turn Clock has 2 components - 1 for updating the number of ATB Frame Updates passed for the same turn, and 1 for updating the battle turn count. It's shown in BattleManager.update_matb_turn and BattleManager.end_matb_turn:

BattleManager.update_matb_turn = function() { // New; Hotspot
// The fps is assumed to be always 60
if ((this._matb_turn_clock += 1) >= $gameSystem.matb.max_turn_unit * 60) {
this._matb_turn_clock = 0;
this.end_matb_turn();
}
//
}; // BattleManager.update_matb_turn

BattleManager.end_matb_turn = function() { // New
var members = $gameParty.battleMembers().concat($gameTroop.members());
members.forEach(function(mem) {
mem.onTurnEnd();
this.refreshStatus();
this._logWindow.displayAutoAffectedStatus(mem);
this._logWindow.displayRegeneration(mem);
}, this);
$gameTroop.increaseTurn();
}; // BattleManager.end_matb_turn

The Coh Rating of the Battle Turn Clock is 1 - functional cohesion, as all it does is to update the battle turn count.


The Setup Inputable Actors has 2 components - 1 for finding such eligible actors, and 1 for setting up the actor command window for that actor. It's shown in Scene_Battle.prototype.update_matb and Scene_Battle.prototype.update_matb_actor_selection:

// actor_indices: The indices of all currently inputable actors
Scene_Battle.prototype.update_matb_actor_selection = function(actor_indices) {
// New; Hotspot
if (this._statusWindow.index() > 0) this._statusWindow.deselect();
if (actor_indices.length <= 0) return;
BattleManager.actor_index = actor_indices[0];
this.startActorCommandSelection();
}; // Scene_Battle.prototype.update_matb_actor_selection

The Coh Rating of the Setup Inputable Actors is 1 - functional cohesion, as all it does is to let players input commands for newly inputable actors.


The OutCou Rating of Setup Inputable Actors to Battler ATB Clock is 1 - message coupling, as all the former needs to know is the latter's function name(in this case, BattleManager._actionBattlers to determine whether it's empty).


The Status Window ATB Bars has 2 components - 1 for checking whether an ATB bar needs to be redrawn, and 1 for redrawing those ATB bars. It's shown in Window_BattleStatus.prototype.refresh_matb_bars and Window_BattleStatus.prototype.draw_actor_matb:

Window_BattleStatus.prototype.refresh_matb_bars = function() { // New; Hotspot
var matb = $gameSystem.matb, actor, rect;
var ox = matb.hp_bar_w + matb.mp_bar_ox + matb.mp_bar_w + matb.atb_bar_ox;
if ($dataSystem.optDisplayTp) { ox += matb.tp_bar_ox + matb.tp_bar_w; }
for (var index = 0, max = this.maxItems(); index < max; index++) {
actor = $gameParty.battleMembers()[index];
if (!actor || !actor.matb_val_ch) continue;
rect = this.gaugeAreaRect(index);
this.draw_actor_matb(actor, rect.x + ox, rect.y);
actor.matb_val_ch = false;
}
}; // Window_BattleStatus.prototype.refresh_matb_bars

/* actor: The actor using the atb bar
* x: The atb bar x position
* y: The atb bar y position
*/
Window_BattleStatus.prototype.draw_actor_matb = function(actor, x, y) {
// New; Hotspot
var matb = $gameSystem.matb, w = matb.atb_bar_w;
var c0 = this.textColor(matb.atb_c1), c1 = this.textColor(matb.atb_c2);
this.drawGauge(x, y, w, actor.matb_val / 100, c0, c1);
this.changeTextColor(this.systemColor());
this.drawText('AP', x, y, this.textWidth('AP'));
}; // Window_BattleStatus.prototype.draw_actor_matb

The Coh Rating of the Status Window ATB Bars is 1 - functional cohesion, as all it does is to always draw the most updated ATB bars for each actor on the status window.


The OutCou Rating of the Status Window ATB Bars to the Battler ATB Clock is 1 - message coupling, as all the former needs to know is the latter's function names(Game_Battler.prototype.matb_val_ch and Game_Battler.prototype.matb_val in this case).






Even with just the 1st glance, It should be 100% crystal clear and obvious that it's the OutCou Rating of ATB Frame Update to Battler ATB Clock and Setup Inputable Actors that really stand out, due to them exhibiting stamp coupling, which is generally considered to be a moderate code smell.


Changing the OutCou Rating of ATB Frame Update to Battler ATB Clock from 3 to 1(message coupling) is easy, simple and small, just by changing BattleManager.update_matb from:

BattleManager.update_matb = function() { // New; Hotspot
$gameParty.aliveMembers().forEach(function(mem) { mem.update_matb(); });
$gameTroop.aliveMembers().forEach(function(mem) { mem.update_matb(); });
if (this._phase !== 'action') this.process_matb_turn();
this.update_matb_turn();
}; // BattleManager.update_matb





To:










BattleManager.update_matb = function() { // New; Hotspot
$gameParty.update_matb();
$gameTroop.update_matb();
if (this._phase !== 'action') this.process_matb_turn();
this.update_matb_turn();
}; // BattleManager.update_matb


Code:
Game_Unit.prototype.update_matb = function() { // New; Hotspot
    this.aliveMembers().forEach(function(mem) { mem.update_matb(); });
}; // Game_Unit.prototype.update_matb





Similarly, changing the OutCou Rating of ATB Frame Update to Setup Inputable Actors from 3 to 1(message coupling) is easy, simple and small, just by changing Scene_Battle.prototype.update_matb from:










Scene_Battle.prototype.update_matb = function() { // New; Hotspot
BattleManager.update_matb();
var actor_indices = BattleManager.action_battlers.filter(function(battler) {
return battler.canInput();
}).map(function(battler) { return battler.index(); });
if (actor_indices.indexOf(this._statusWindow.index()) < 0) {
this.update_matb_actor_selection(actor_indices);
}
this._statusWindow.refresh_matb_bars();
}; // Scene_Battle.prototype.update_matb





To:










BattleManager.matb_inputable_actor_indices = function() { // New; Hotspot
return this._action_battlers.filter(function(battler) {
return battler.canInput();
}).map(function(battler) { return battler.index(); });
}; // BattleManager.matb_inputable_actor_indices

Scene_Battle.prototype.update_matb = function() { // New; Hotspot
BattleManager.update_matb();
this.update_matb_actor_input();
this._statusWindow.refresh_matb_bars();
}; // Scene_Battle.prototype.update_matb

Scene_Battle.prototype.update_matb_actor_input = function() { // New; Hotspot
var actor_indices = BattleManager.matb_inputable_actor_indices();
if (actor_indices.indexOf(this._statusWindow.index()) >= 0) return;
this.update_matb_actor_selection(actor_indices);
}; // Scene_Battle.prototype.update_matb_actor_input







Now the Com Coh/Cou Digraph of the top layer of MATB becomes really excellent - Both the Coh Rating and maximum InCou Rating/OutCou Rating are 1, which are both ideal, and no component has too many subcomponents. Also, all the arrows are necessary, because:


1. The Battle Frame Update needs to know how to call the ATB Wait Condition in order to determine whether the ATB Frame Update can be run


2. The Battle Frame Update needs to know how to call the ATB Frame Update in order for the latter to be run by the former


3. The ATB Frame Update needs to know how to call the Battler ATB Clock for each battler(via game party/troop without directly involving any battler in this case) in order to update their Battler ATB Clock


4. The ATB Frame Update needs to know how to call the Setup New Action Execution Subject in order to let such eligible battlers to execute actions


5. The ATB Frame Update needs to know how to call the Battle Turn Clock in order to update the battle turn count


6. The ATB Frame Update needs to know how to call the Setup Inputable Actors to let players input commands for such eligible actors


7. The ATB Frame Update needs to know how to call the Status Window ATB Bars to always keep them up to date


8. The Setup New Action Execution Subject needs to know how to call the Battler ATB Clock for each battler in order to determine which battlers are eligible(having inputted all actions with confirmation flags set) to be the new Action Execution Subject


9. The Setup Inputable Actors needs to know how to call the Battler ATB Clock for each battler in roder to determine which battlers are eligible(having full Battler ATB Clock with no actions inputted) to have the actor command windows setup


10. The Status Window ATB Bar needs to know how to call the Battler ATB Clock for each battler in order to read their values to always display them accurately(keep up to date)


Moreover, the top layer of MATB itself doesn't contain too many components.


To sum up, having a basic knowledge on how MATB works should be easy, simple and small.


Besides, recall that the InCou Rating Sum of a component can be used to measure how easily that component can be broken due to changes to any other components it depends on, and the OutCou Rating Sum of a components can be used to measure how easily that component can brake some other components depending on it due to its changes.


In this case, the Battler ATB Clock has the largest InCou Rating Sum(original: 6, refactored: 4), while the ATB Frame Update has the largest OutCou Rating Sum(original: 9, refactored: 5). It means that refactoring the Battler ATB Clock should be done with the largest amount of care and caution, while the ATB Frame Update is likely the one being changed the most frequently unless it's indeed nicely written.


Finally, this Com Coh/Cou Digraph can also be used to reveal some parts of the overall flow of the top layer of MATB.


In this case, we can at least deduce that the flow starts from Battle Frame Update, as it's the only components having 0 InCou Rating Sum.


Similarly:


1. Both the ATB Wait Condition and ATB Frame Update can only be called by Battle Frame Update


2. All the Setup New Action Execution Subject, Battle Turn Clock , Setup Inputable Actors and Status Window ATB Bars can only be called by ATB Frame Update


Note that the flow involving the Battler ATB Clock isn't as certain as the rest of the components just by looking at this Com Coh/Sou Digraph alone, meaning that merely depending on a Com Coh/Sou Digraph to reveal the entirety of the overall flow's somehow unreliable.


Furthermore, as InCou Rating of component A from component B can also indicate how much component B knows about component A, while the OutCou Rating is the vice versa, the components with the largest InCou Rating Sum sometimes shows the largest amount of details of the flow, while those with the largest OutCou Rating Sum sometimes shows the largest portion of frameworks within the flow.


Therefore, in this case, the ATB Frame Update is the center of the flow of MATB, while the Battler ATB Clock is the center of the details of MATB.


On a side note: These just apply occasionally. For instance, those on the top layer of systems using the Core Addon Approach is the complete opposite - The core plugin has the largest InCou Rating Sum and the smallest OutCou Rating Sum, yet it's the center of the flow of the whole system, and it contains the least amount of details(which are delegated to the addon plugins). It's because the core plugin defines the flow, and each addon plugin needs to know the flow in order to add details.


















Summary

In practice, using a Com Coh/Cou Digraph to analyze the structural health of a system involves the following steps:


1. Have a basic knowledge on how that system itself works


2. Begin from the top layer


3. Draw the Com Coh/Cou Digraph for the current layer of that system


4. Analyze the number of subcomponents, Coh Rating, InCou Rating/OutCou Rating, InCou Rating Sum, OutCou Rating Sum, and the necessity of each arrow for each components


5. Analyze the number of components, the sum of number of subcomponents, Coh Rating Sum and Cou Rating Sum for the current layer


6. Move to a lower layer(or stop if the lowest layer's reached)


7. Repeat from step 3


Besides, a Com Coh/Cou Digraph can also be used to reveal some parts but not the entirety of the overall flow of its layer.


Typically, components having InCou Rating Sum as 0 are likely entry points(if any), and exit points, if any, are probably not those having nonzero OutCou Rating Sum.


Moreover, as InCou Rating of component A from component B can also indicate how much component B knows about component A, while the OutCou Rating is the vice versa, the components with the largest InCou Rating Sum sometimes shows the largest amount of details of the flow, while those with the largest OutCou Rating Sum sometimes shows the largest portion of frameworks within the flow.


Just note that these just apply occasionally. For instance, those on the top layer of systems using the Core Addon Approach is the complete opposite - The core plugin has the largest InCou Rating Sum and the smallest OutCou Rating Sum, yet it's the center of the flow of the whole system, and it contains the least amount of details(which are delegated to the addon plugins). It's because the core plugin defines the flow, and each addon plugin needs to know the flow in order to add details.
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

Couple hours of work. Might use in my game as a secret find or something. Not sure. Fancy though no? :D
Holy stink, where have I been? Well, I started my temporary job this week. So less time to spend on game design... :(
Cartoonier cloud cover that better fits the art style, as well as (slightly) improved blending/fading... fading clouds when there are larger patterns is still somewhat abrupt for some reason.
Do you Find Tilesetting or Looking for Tilesets/Plugins more fun? Personally I like making my tileset for my Game (Cretaceous Park TM) xD
How many parameters is 'too many'??

Forum statistics

Threads
105,862
Messages
1,017,045
Members
137,569
Latest member
Shtelsky
Top