-
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][2]
Some 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. It is worth noting that a method can be labeled with one or more stereotypes from each category.
Stereotype Category | Stereotype | Description |
---|---|---|
Structural Accessor | get | Returns a data member |
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 about data members through parameters | |
Structural Mutator | set | Modifies 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 belonging to classes other than itself (parameter, local variable, data member, or return value) |
controller | Changes only an external object’s state (not this) | |
wrapper | Does not change an object’s state. Has at least one free function call | |
Degenerate | incidental | Does not read/change an object’s state. Has no calls |
stateless | Does not read/change an object’s state. Has at least one call to other class methods or to a free function | |
empty | Has no statements |
TABLE 1. Taxonomy of Method Stereotypes.
A structural accessor is a method that returns information about the state of an object. There are four types: get, predicate, property, and void-accessor.
A get is a method returns the value of some data member
Examples for C++:
// @stereotype get
double AxisModelBase::getTickStep() const {
return m_tick_step;
}
// @stereotype get
bool RootBranch::isUseable() const {
return m_useable;
}
Examples for C#:
// @stereotype get
protected override string GetSourceObjectEventName()
{
return _eventName;
}
internal string Namespace
{
// @stereotype get
get
{
return this.nameSpace;
}
}
Examples for Java:
// @stereotype get
public final boolean isTimeout() {
return timeout;
}
// @stereotype get
long cachedEventCount() {
return size;
}
A predicate is a method that computes a Boolean value using data member values and returns it.
Examples for C++:
// @stereotype predicate
bool RootBranch::isMultiDimensional() const {
return !(m_number_elements == 1 );
}
// @stereotype predicate
bool RepBase::isSelected() const {
return m_desel == false;
}
Examples for C#:
// @stereotype predicate
internal bool IsPassThruObjectNeeded()
{
return (_passThru) && (!this.DidUserSuppressTheOperation) && (!this.JobHadErrors);
}
// @stereotype predicate
internal bool HostInNestedPrompt()
{
if (NestedPromptCount > 0)
{
return true;
}
else
{
return false;
}
}
Examples for Java:
// @stereotype predicate
public boolean hasThrowable() {
return done && error != null;
}
// @stereotype predicate
public boolean isOnComplete() {
return value == null;
}
A property is a method that returns information (not Boolean) about an object using data member values.
// @stereotype property
double Range::fraction(double value) const {
return (value - m_min)/(m_max - m_min);
}
// @stereotype property
inline double Range::length() const {
return (m_max - m_min);
}
Examples for C#:
// @stereotype property
public override string ToString()
{
return "LoadObject(" + (_value ?? "null") + ")";
}
// @stereotype property
internal int GetSessionsCount()
{
return this.curCimSessionsById.Count;
}
Examples for Java:
// @stereotype property
public final int requestFusion(int mode) {
return mode & ASYNC;
}
// @stereotype property
int calcElementOffset(long index) {
return (int)index & mask;
}
A void-accessor is a method that returns information about an object through a parameter.
Examples for C++:
void NumArrayTuple::fillShape(std::vector<intptr_t>& shape, unsigned int column ) const {
shape.clear ();
numeric::array na = getNumArray ( column );
shape = num_util::shape ( na );
}
// @stereotype void-accessor
inline void visible_cells(int& r1, int& r2, int& c1, int& c2) {
r1 = toprow;
r2 = botrow;
c1 = leftcol;
c2 = rightcol;
}
Examples for C#:
// @stereotype void-accessor
internal bool IsFuzzyMatch(string candidate, string pattern, out int score)
{
score = GetDamerauLevenshteinDistance(candidate, pattern);
return score <= MinimumDistance;
}
Examples for Java:
// @stereotype void-accessor
void dequantize(int[] dataUnit, int iComp) {
int[] qTable = quantizationTables[frameComponents[componentIds[iComp]][TQI]];
for (int i = 0; i < dataUnit.length; i++) {
int zzIndex = ZigZag8x8[i];
dataUnit[zzIndex] = dataUnit[zzIndex] * qTable[i];
}
}
A structural mutator is a method that modifies the state of an object. There are three types: set, command, and non-void-command.
A set method is a mutator that modifies the value of a data member.
Examples for C++;
// @stereotype set
void dataSource::setName(const string& name){
m_ds_name = name;
}
// @stereotype set
void ListTuple::setShape(std::vector<unsigned int>& shape) {
m_shape = shape;
}
Examples for C#:
// @stereotype set
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
_disposed = true;
}
internal TypeTable TypeTable
{
// @stereotype set
set { _serializer.TypeTable = value; }
}
Examples for Java:
// @stereotype set
public void setDone()
{
this.done = true;
}
// @stereotype set
public void accept(Integer t)
{
items++;
}
A command method is a mutator that modifies the state of an object in a complex way.
Examples for C++:
// @stereotype command
void DataSource::copyPrivate(const DataSource& other) {
m_ds_name = other.m_ds_name;
m_is_null = other.m_is_null;
m_labels = other.m_labels;
m_shape = other.m_shape;
m_title = other.m_title;
}
Examples for C#:
public uint MaxEnvelopeSizeKB
{
// @stereotype non-void-command
set
{
maxenvelopesizekb = value;
maxenvelopesizekbSet = true;
base.SetParameter(value, nameMaxEnvelopeSizeKB);
}
}
Examples for Java:
// @stereotype command
public void setup() {
flowable = Flowable.just(1);
observable = Observable.just(1);
single = Single.just(1);
maybe = Maybe.just(1);
completable = Completable.complete();
}
A factory method is a creational method that creates an object and returns it to the client.
Examples for C++:
// @stereotype factory stateless
CutRangeRep* CutRangeRep::clone() {
return new CutRangeRep(*this);
}
Examples for C#:
// @stereotype factory stateless
public LocalGroup Clone()
{
return new LocalGroup(this);
}
Examples for Java:
// @stereotype factory wrapper stateless
public Processor<Integer, Integer> createIdentityProcessor(int bufferSize) {
UnicastProcessor<Integer> up = UnicastProcessor.create();
return new RefCountProcessor<>(up);
}
Collaborational methods deal with objects of other classes. There are two types: collaborator, and controller.
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 through some data member(s).
Examples for C++:
// @stereotype collaborator
void DisplayController::fixLogIfBinned ( const PlotterBase* plotter, DataRep* rep ) const {
setBinner ( plotter, rep, Axes::X );
setBinner ( plotter, rep, Axes::Y );
}
Examples for C#:
// @stereotype property collaborator
private LineOutput InstantiateLineOutputInterface()
{
PrinterLineOutput printOutput = new(_printerName);
return (LineOutput)printOutput;
}
Examples for Java:
// @stereotype command collaborator
public void flowFlatMapIterable1(Blackhole bh) {
flowFlatMapIterable1.subscribe(new PerfConsumer(bh));
}
A controller method only changes the state of external objects.
Examples for C++:
// @stereotype controller
void BinnerAxisXML::setAttributes(XmlElement* tag, const BinnerAxis& binner ) {
const string & type = binner.name();
tag->setAttribute ( m_type, type );
const Range & range = binner.getRange ();
double high = range.high();
double low = range.low ();
tag->setAttribute ( m_high, high );
tag->setAttribute ( m_low, low );
double width = binner.getBinWidth ();
tag->setAttribute ( m_width, width );
}
Examples for C#:
// @stereotype controller
public void TestClearContent()
{
FileSystemProvider fileSystemProvider = new FileSystemProvider();
ProviderInfo providerInfoToSet = GetProvider();
fileSystemProvider.SetProviderInformation(providerInfoToSet);
fileSystemProvider.Context = new CmdletProviderContext(GetExecutionContext());
fileSystemProvider.ClearContent(testPath);
Assert.Empty(File.ReadAllText(testPath));
}
Examples for Java:
// @stereotype controller
void subscribe(Flowable<Integer> f, Blackhole bh) {
PerfAsyncConsumer consumer = new PerfAsyncConsumer(bh);
f.subscribe(consumer);
consumer.await(count);
}
A wrapper method does not change an object’s state and has at least one free function call.
Examples for C++:
void OpenGLWindow::flush()
{
glFinish();
glXSwapBuffers(m_display,m_window);
}
Examples for C#:
// @stereotype controller
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
File.Delete(testPath);
}
}
Examples for Java:
public void onSubscribe(@NonNull Disposable d) {
DisposableHelper.setOnce(upstream, d);
}
A degenerate method is a method that has no use of the object's state. There are three types: incidental, stateless, and empty[8]
An incidental method is a method that does not read or change an object’s state and has no calls.
Examples for C++:
// @stereotype incidental
bool NTupleChiSqFCN::needsIntegrated() const {
return false;
}
Examples for C#:
// @stereotype incidental
protected override string GetSourceObjectEventName()
{
return "CimIndicationArrived";
}
Examples for Java:
// @stereotype incidental
public long maxElementsFromPublisher() {
return 1;
}
A stateless method is a method that does not read or change an object’s state directly. This method has at least one call to other class methods or to a free function.
Examples for C++:
// @stereotype wrapper stateless
virtual double errorDef () const {
return up();
}
Examples for C#:
// @stereotype wrapper stateless
public override void EnterNestedPrompt()
{
EnterNestedPrompt(null);
}
Examples for Java:
// @stereotype wrapper stateless
public void successDetaches() throws Exception {
Disposable d = Disposable.empty();
final WeakReference<Disposable> wr = new WeakReference<>(d);
TestObserver<Integer> to = new Maybe<Integer>() {
@Override
protected void subscribeActual(MaybeObserver<? super Integer> observer) {
observer.onSubscribe(wr.get());
observer.onSuccess(1);
observer.onSuccess(2);
};
}
.onTerminateDetach()
.test();
d = null;
System.gc();
Thread.sleep(200);
to.assertResult(1);
assertNull(wr.get());
}
An empty is a method that has no statements (except for comments).
Examples for C++:
// @stereotype empty
void hippodraw::Observer::willDelete(const Observable*) {
// do nothing, default behaviour
}
Examples for C#:
// @stereotype empty
internal virtual void RemoveCommandTransportManager(Guid powerShellCmdId)
{
}
Examples for Java:
// @stereotype empty
public void onSubscribe(Disposable d)
{
}
[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.