Why Abstract Thinking Is the Key to Scalable Software Design
The article explains how abstract thinking—extracting common traits, ignoring irrelevant details, and managing hierarchical levels—empowers programmers to write more reusable, maintainable code, illustrated with philosophical analogies, OOP examples, and concrete refactoring of type‑casting logic.
During a promotion meeting at Alibaba, judges often ask, “Can your success be replicated?” The author reflects that this question distinguishes luck from the ability to consistently solve problems, especially for knowledge‑workers whose core competency is abstract thinking.
What Is Abstract Thinking?
Abstract thinking involves extracting common features from concrete instances and representing them with symbols. The author likens naming in programming to this process: a good name requires identifying the essence of an object and discarding irrelevant details.
Illustrating Abstraction with Art
Using Picasso’s abstract cow versus a realistic water buffalo, the article shows how abstraction removes most details, keeping only essential traits (horns, head, tail). This mirrors an abstract class in object‑oriented programming, which captures the shared essence of all subclasses.
Three Characteristics of Abstraction
Ignoring details : The higher the abstraction, the more details are omitted, similar to an abstract class or interface.
Representing common properties : An abstract class defines the shared attributes of its subclasses.
Hierarchical nature : Higher‑level abstractions have narrower meaning but broader applicability; for example, “cow” is more abstract than “water buffalo.”
Choosing the Right Abstraction Level
Programmers must balance abstraction depth to match business needs—neither too high (vague) nor too low (over‑specific). The article gives a fruit‑class example: defining separate RedApple and GreenApple classes is low‑level; abstracting to Apple with a color property, then to Fruit, yields a more reusable hierarchy.
When Type Casting Signals a Bad Abstraction
Frequent use of instanceof or explicit casts often indicates that the current abstraction is insufficient. In the example, Apple.isSweet() and Watermelon.isJuicy() belong to low‑level subclasses, forcing casts in a FruitPicker utility.
public class FruitPicker {
public List<Fruit> pickGood(List<Fruit> fruits) {
return fruits.stream().filter(e -> check(e)).collect(Collectors.toList());
}
private boolean check(Fruit e) {
if (e instanceof Apple) {
if (((Apple) e).isSweet()) {
return true;
}
}
if (e instanceof Watermelon) {
if (((Watermelon) e).isJuicy()) {
return true;
}
}
return false;
}
}Raising the abstraction by adding an isTasty() method to the Fruit base class eliminates the need for casts and satisfies the Liskov Substitution Principle.
public class FruitPicker {
public List<Fruit> pickGood(List<Fruit> fruits) {
return fruits.stream().filter(e -> check(e)).collect(Collectors.toList());
}
private boolean check(Fruit e) {
return e.isTasty(); // No instanceof or cast needed
}
}Takeaway
Whenever you reach for instanceof or a cast, consider whether the abstraction hierarchy can be elevated. A higher‑level abstraction reduces coupling, improves extensibility, and aligns code with solid design principles.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
