-
Notifications
You must be signed in to change notification settings - Fork 0
Method Stereotypes
A method stereotype is a concise high-level description of the role of a method in a software system. It is a simple form of documentation that is used to provide additional information about the behavioral aspects and responsibilities of a method. Method stereotype information can be used to lay the foundation of more sophisticated forms of documentations and design recovery.[1]
Uses of method stereotype information include determining the stereotypes of classes,[5] improving the precision of metrics calculations,[1] measuring the level of improvement or degradation of a method when its role changes,[3] improving feature location in source code,[4] generating natural language summaries for methods,[6] characterizing commits on version control systems into different types, [7] and creating signature descriptors for software systems.[8]
Method stereotypes can be classified into five main categories depending on the role of a method[1].
Stereotype Category | Stereotype | Description |
---|---|---|
Structural Accessor | get | Returns a data member |
non-const-get | ||
predicate | Returns Boolean value that is not a data member | |
property | Returns non-Boolean value that is not a data member | |
void-accessor | Returns information via a parameter | |
Structural Mutator | set | Sets a data member |
command | Performs a complex change to the object’s state. | |
non-void-command | ||
Creational | constructor | Creates and/or destroys objects |
copy-constructor | ||
destructor | ||
factory | ||
Collaborational | collaborator | Works with objects (parameter, local variable, pointer/reference, or return object) |
controller | Changes only an external object’s state (not this) | |
Degenerate | stateless (a.k.a incidental or pure stateless) | Does not read/change the object’s state. No calls to other methods of the same class |
wrapper (a.k.a stateless) | Does not read/change the object’s state. One call to other methods of the same class | |
empty | Has no statements |
TABLE 1. Taxonomy of Method Stereotypes.[2]
A structural accessor is a read-only method that returns information about the state of an object. An accessor method does not modify or change the state of the object, that is, it keeps the data members as it. There are four types: get, predicate, property, and void-accessor.[1]
A get method is a simple accessor that returns the value of some data member.
// @stereotype get
bool dataSource::isNull() const{
return m_is_null;
}
// @stereotype non-const-get
const string& dataSource::getName() const;
return m_ds_name;
}
A non-const-get method is a get method that is not constant.
// @stereotype non-const-get
std::vector<int> dataSource::getValues(){
return values;
}
A predicate method is an accessor that computes a Boolean value from the data member(s) and returns it.
// @stereotype predicate
bool dataSource::isValidLabel(const string& label) const{
vector<string>::const_iterator first = find(m_labels.begin(), m_labels.end(), label);
bool yes = first != m_labels.end();
return yes;
}
A property method is an accessor that returns information (not Boolean) about an object using data member values. It can compute a result, compare objects, or convert an object.
// @stereotype property
unsigned int dataSource::columns () const{
return static_cast<unsigned int>(m_labels.size());
}
// @stereotype property
int indexOfMin(int index) const {
int minIndex = 0;
for (int i = 0; i < data.size(); ++i) {
if (data[i] < data[minIndex])
minIndex = i;
}
return minIndex;
}
A void-accessor method is an accessor that returns information about an object through a parameter.
// @stereotype void-accessor
void minElement(Element& element) const {
int minIndex = 0;
for (int i = 0; i < data.size(); ++i) {
if (data[i] < data[minIndex])
minIndex = i;
}
element = data[minIndent];
}
A structural mutator is a method that modifies the state of an object. There are three types: set, command, and non-void-command.[1]
A set method is a mutator that modifies the value of a data member.
// @stereotype set
void dataSource::setName(const string& name){
m_ds_name = name;
}
// @stereotype set
boolean setLabels(const vector<string>& v){
m_labels = v;
return true;
}
A command method is a mutator that modifies the state of an object in a complex way. Typically, a command method does not return any value or returns a Boolean value.
// @stereotype command
void clear();
// @stereotype command
bool draw(int x, int y);
A non-void-command method is a mutator that modifies the state of an object in a complex way and returns a non-Boolean value.
// @stereotype non-void-command
int reshape(int x, int y);
// @stereotype command
double reserve(int count);
A creational method is a method that creates and/or destroys objects. There are four types: constructor, copy-constructor, destructor, and factory[1]
// @stereotype constructor
displayController();
// @stereotype copy-constructor
displayController(const dataSource&);
// @stereotype destructor
~displayController();
A factory method is a creational method that creates an object and returns it to the client.
// @stereotype factory
plotterBase* displayController::createDisplay(const string& name){
dataRepController* controller = dataRepController::instance();
dataRep* rep = controller->createDataRep(name);
return createDisplay(rep);
}
Collaborational methods deal with objects of other classes. There are two types: collaborator, and controller[1]
A collaborator method works on objects that belong to classes other than itself. These objects are usually passed as parameters, created as local variables, or accessed indirectly through a pointer/reference from some data member.
// @stereotype collaborator
bool displayController::hasControlPoints(const PlotterBase* plotter) const{
bool yes = false;
const binToColor* rep = plotter->getValueRep();
if (rep != 0) {
yes = rep->hasControlPoints();
}
return yes;
}
A controller method works only on objects that belong to classes other than itself.
// @stereotype controller
void displayController::setBinner(PlotterBase* plotter, hippodraw::Axes::Type axis){
int number = plotter->getNumDataReps();
for (int i = 0; i < number; i++) {
dataRep* datarep = plotter->getDataRep(i);
setBinner(plotter, datarep, axis);
}
}
A degenerate method is a method that has no use of the object's state. There are three types: stateless, wrapper, and empty[8]
An stateless method is a method that does not read or change an object’s state directly nor indirectly and does not make calls to other methods of the same class.
// @stereotype stateless
point add(const point& n1, const point& n2) {
return n1 + n2;
}
A wrapper method is a method that does not read or change an object’s state directly nor indirectly. This method can make one call to other methods of the same class.
// @stereotype wrapper
void sort(point& n1, point& n2) {
sort(n1, n2, [](auto n1, auto n2){ return n1 < n2; });
}
An empty method is a method that has no statements. Probably created to be overridden later.
// @stereotype empty
void point::process() const {
}
A method can be labeled with one or more stereotypes. The stereotypes in the categories Accessor, Mutator, and Creational are known as primary stereotypes. The stereotypes in the categories Collaborational and Degenerate can be primary as well as secondary stereotypes. A method can only have one primary stereotype and one or more secondary stereotypes. For example, a set-collaborator is a method that changes an object of another class.[8]
// @stereotype collaborator factory
plotterBase* pisplayController::createDisplay(const string& name){
pataRepController* controller = pataRepController::instance();
pataRep* rep = controller->createDataRep(name);
return createDisplay(rep);
}
// @stereotype collaborator property
const vector<string>& pisplayController::getDisplayTypes() const{
pataRepFactory* factory = pataRepFactory::instance();
return factory->names();
}
// @stereotype collaborator command
void setIntervalCount (const PlotterBase* plotter, int count){
int i = activeDataRepIndex(plotter);
if (i < 0) return;
dataSource* ds = getDataSource(plotter, i);
NTuple* ntuple = dynamic_cast <NTuple*> (ds);
if (ntuple != 0) ntuple->setIntervalCount(count);
}
[1] Dragan, N., Collard, M. L., & Maletic, J. I. (2006, September). Reverse engineering method stereotypes. In 2006 22nd IEEE International Conference on Software Maintenance (pp. 24-34). IEEE.
[2] Guarnera, D., Collard, M. L., Dragan, N., Maletic, J. I., Newman, C., & Decker, M. (2018, September). Automatically Redocumenting Source Code with Method and Class Stereotypes. In 2018 IEEE Third International Workshop on Dynamic Software Documentation (DySDoc3) (pp. 3-4). IEEE.
[3] Decker, M. J., Newman, C. D., Dragan, N., Collard, M. L., Maletic, J. I., & Kraft, N. A. (2018, May). A taxonomy of how method stereotypes change. In Proceedings of the 40th International Conference on Software Engineering: Companion Proceeedings (pp. 337-338).
[4] Alhindawi, N., Dragan, N., Collard, M. L., & Maletic, J. I. (2013, September). Improving feature location by enhancing source code with stereotypes. In 2013 IEEE International Conference on Software Maintenance (pp. 300-309). Ieee.
[5] Dragan, N., Collard, M. L., & Maletic, J. I. (2010, September). Automatic identification of class stereotypes. In 2010 IEEE International Conference on Software Maintenance (pp. 1-10). IEEE.
[6] Abid, N. J., Dragan, N., Collard, M. L., & Maletic, J. I. (2015, September). Using stereotypes in the automatic generation of natural language summaries for c++ methods. In 2015 IEEE International Conference on Software Maintenance and Evolution (ICSME) (pp. 561-565). IEEE.
[7] Dragan, N., Collard, M. L., Hammad, M., & Maletic, J. I. (2011, September). Using stereotypes to help characterize commits. In 2011 27th IEEE International Conference on Software Maintenance (ICSM) (pp. 520-523). IEEE.
[8] Dragan, N., Collard, M. L., & Maletic, J. I. (2009, September). Using method stereotype distribution as a signature descriptor for software systems. In 2009 IEEE International Conference on Software Maintenance (pp. 567-570). IEEE.