imperative abstraction
This bad smell is caused by the conversion of the operation into a class, which is manifested in that only one method is defined in the class, and sometimes the class name and the method name are the same. This bad smell is also often manifested in that the data that the method operates on is located in another class.
Why not imperative abstraction?
The fundamental principle of object orientation is to identify things in the real world and use abstractions to represent them. In the solution domain, the objects of the problem domain must be represented. For this purpose , the realization method of mapping domain entities can be adopted . Each abstract class must encapsulate the data and related methods. A class that contains only one operation is not abstract at all, especially if the data it operates on resides elsewhere. In this way, many methods that operate on the same data are located in different classes, which reduces the cohesion of the class and violates the principles of encapsulation and modularity.
The underlying reason for imperative abstraction
process thinking
Data and methods of manipulating that data are encapsulated in different classes, typical of procedural thinking.
Example analysis
Let's look at the report generation function, which uses the CreateReport, CopyReport, DisplayReport and other classes. Each of these classes contains only one method. Data items related to the report, such as the report name, are placed in the Report class. Obviously there is "imperative abstraction" in the program, this bad smell not only increases the number of classes (at least 4 classes, ideally only 1 class), but also separates cohesive methods, increasing development and Maintenance complexity. The design adopts " functional decomposition " rather than " object-oriented decomposition ".
public class Report
{
public string ReportName { get; set; }
}
public class CreateReport
{
public void Create()
{
//Create
}
}
public class DisplayReport
{
public void Display()
{
//Display
}
}
public class CopyReport
{
public void Copy()
{
//Copy
}
}
Refactoring: We moved all the methods in the class that smelled "imperative abstraction" into the Report class, then the Report class became a proper abstraction and eliminated the "imperative abstraction" smell.
Refactored implementation:
public class Report
{
public string ReportName { get; set; }
public void Create()
{
//Create
}
public void Display()
{
//Display
}
public void Copy()
{
//Copy
}
}
realistic considerations
embodiment
Reification refers to the promotion of something that is not an object into an object. Once a behavior is materialized, it can be stored, passed, and transformed. Concretization can increase the flexibility of the system, but at the cost of increasing the complexity of the system.
Many design patterns use materialization: state pattern, command pattern, strategy pattern.
It's not a bad smell to consciously promote something that wasn't originally an object to be an object in order to improve reusability, flexibility, and extensibility.
Reference: "Software Design Refactoring"