Process oriented and object oriented thinking
In most cases, we start programming in a procedural language (C) and then move into an object-oriented language such as Java, C#, Python, etc. However, when using object-oriented programming, it is possible to retain part of the process oriented thinking, or there is some wrong object-oriented thinking.
Here I will use two examples to compare the difference between process-oriented and object-oriented thinking, and after each example is implemented, I will give a practical example and a false example to illustrate two problems:
- There is some procedural scripting in object-oriented programming.
- There are some object modeling errors in object modeling.
A classic example of the difference between process orientation and object orientation is called “Putting elephants in the Fridge” :
- The man opened the refrigerator door
- The man put the elephant in
- I shut the refrigerator door
However, it evolved into another version of “Putting the Elephant in the Fridge” :
- The man opened the refrigerator door
- The elephant walks into the fridge
- I shut the refrigerator door
In one version, the elephant was put in the refrigerator, and in the other, the elephant walked into the refrigerator. You should implement both of these use cases using procedural and object-oriented implementations, which means you should implement the two use cases loading into the refrigerator and walking into the refrigerator respectively using procedural and object-oriented implementations. Then we can do a horizontal comparison, using the process-oriented implementation of “Put the elephant in the refrigerator” versus the object-oriented implementation of “Put the elephant in the refrigerator.” Instead of using a process-oriented implementation to load into the refrigerator, using an object-oriented implementation to walk into the refrigerator and cross-compare. The following table:
Process oriented | object-oriented |
---|---|
Put into the fridge | Put into the fridge |
Into the refrigerator | Into the refrigerator |
Put the elephant in the fridge
Let’s start with a process-oriented example of loading an elephant into a refrigerator:
// Define a push method that manipulates arrays.
declare function push(array: any[], element: any)
class Elephant {}class Fridge {
public status: string
public elephants: Elephant[] = []
}
function open(fridge: Fridge) {
fridge.status = "opened"
}
function put(fridge: Fridge, elephant: Elephant) {
push(fridge.elephants, elephant)
}
function close(fridge: Fridge) {
fridge.status = "closed"
}
function main() {
const elephant = new Elephant()
const fridge = new Fridge()
open(fridge)
put(fridge, elephant)
close(fridge)
}
Copy the code
The Elephant and Fridge objects are used to simulate the structure, and then the three functions of open, put and close are used to complete the corresponding business logic respectively.
Then an example of an object-oriented implementation of putting an elephant in a fridge:
class Elephant {}class Fridge {
status: string
elephants: Elephant[] = []
open() {
this.status = "opened"
}
put(elephant: Elephant) {
this.elephants.push(elephant)
}
close() {
this.status = "closed"}}function main() {
const elephant = new Elephant()
const fridge = new Fridge()
fridge.open()
fridge.put(elephant)
fridge.close()
}
Copy the code
These two examples seem to illustrate some of the differences between procedural and object orientation. But how can these two kinds of thinking influence and help us in our daily work?
For example, we want to develop a smart home system, which has a function: “smart butler” can put some fruits into the refrigerator, and after the operation is completed, the smart butler will update the refrigerator information by calling the back-end service interface, and then the owner can check the items in the refrigerator through the mobile phone. Now the “smart home system” will be designed as a back-end service that can serve smart butlers and mobile terminals.
Using a process-oriented implementation:
class FridgeService {
private readonly fridgeRepository: FridgeRepository
constructor(fridgeRepository: FridgeRepository) {
this.fridgeRepository = fridgeRepository
}
// /v1/fruits/:fridgeId/open
public openFridge(fridgeId: string): Fridge {
const fridge = this.fridgeRepository.findById(fridgeId)
fridge.status = "opened"
return this.fridgeRepository.save(fridge)
}
// /v1/fruits/:fridgeId/put
public putFruit(fridgeId: string.fruit: Fruit): Fridge {
const fridge = this.fridgeRepository.findById(fridgeId)
if(fridge.status ! = ="opened") {
throw new Error("The fridge is not open")
}
fridge.fruits.push(fruit)
return this.fridgeRepository.save(fridge)
}
}
Copy the code
This is probably the most common way to write business logic directly inside a Service, but it’s not a good procedural or object-oriented coding rule. First of all, you don’t encapsulate the business into function functions as you do with procedures, and you don’t encapsulate the business into methods of entity objects as you do with objects. This is scripted development.
Using an object-oriented implementation:
class Fridge {
status: string
fruits: Fruit[] = []
open() {
this.status == "opened"
}
isOpened() {
return this.status === "opened"
}
put(fruit: Fruit) {
if (!this.isOpened()) {
throw new Error("The fridge is not open")}this.fruits.push(fruit)
}
}
class FridgeService {
// /v1/fruits/:fridgeId/open
public openFridge(fridgeId: string): Fridge {
const fridge = this.fridgeRepository.findById(fridgeId)
fridge.open() // Open fridge
return this.fridgeRepository.save(fridge)
}
// /v1/fruits/:fridgeId/put
public putFruit(fridgeId: string.fruit: Fruit): Fridge {
const fridge = this.fridgeRepository.findById(fridgeId)
fridge.put(fruit) // Put fruit
return this.fridgeRepository.save(fridge)
}
}
Copy the code
From the beginning of the “elephant into the refrigerator” two kinds of implementation and “smart home system” two kinds of implementation, in fact, there are three kinds of programming: small function thinking oriented process, scripting oriented process and object-oriented programming.
By comparing these three approaches, we should find that scripted development is the easiest, cheapest to learn, and most common. However, projects developed in this mode can become difficult to maintain over time. He almost has no function abstraction, only on a logic function, better script code to a functional decomposition, but haven’t reached like “put an elephant into a refrigerator” process for example, the refinement of a business function is decomposed into: open the door (open), put it in (put), closed (close) function of these functions. Once refined it is a process-oriented process with small function thinking. If you’re currently using a purely object-oriented, non-multiparadigm language like Java or C#, you don’t fit into either mindset. You should be coding with an object-oriented mindset in an object-oriented language, not with a process-oriented mindset in an object-oriented language. When it comes to developing object-oriented thinking, “if there’s a downside, it’s the price to pay for mastering it,” as Ideas for Java programming puts it.
The elephant walks into the fridge
Using a process-oriented implementation:
function into(elephant: Elephant, fridge: Fridge) {
push(fridge.elephants, elephant)
}
function main() {
const elephant = new Elephant()
const fridge = new Fridge()
open(fridge)
into(elephant, fridge) // The elephant walks into the refrigerator
close(fridge)
}
Copy the code
This is not much different from the process-oriented implementation of putting an elephant in a refrigerator. Just put(elephant, fridge) instead of into(elephant, fridge), but this one parameter to the other is the sequential description of programming language and natural language, or the difference between active and passive, active walking, passive putting, Initiative and passivity are important concepts in software architecture.
Using an object-oriented implementation:
class Elephant {
into(fridge: Fridge) {
fridge.put(this)}}function main() {
const elephant = new Elephant()
const fridge = new Fridge()
fridge.open()
elephant.into(fridge) // The elephant walks into the refrigerator.
fridge.close()
}
Copy the code
Such use cases as “elephant walks into refrigerator” still exist in real business, for example: automatic storage of intelligent cars. When the car is told to enter the garage, the intelligent car can automatically complete the storage operation.
However, some of the code implementation of writing “elephant walks into refrigerator” has some errors. Such as:
const fridge = new Fridge()
const elephant = new Elephant()
fridge.open()
elephant.into() // Error
fridge.close()
Copy the code
The biggest problem is the elephant.into() method call. You can see that into() is an empty parameter, so that doesn’t have anything to do with the fridge object, where does the elephant go? So this implementation is a bit of a rigor and a bit of a thinking error.
Open source electricity
Mallfoundry is a fully open source multi-merchant e-commerce platform developed using Spring Boot. It can be embedded in existing Java programs or run as a service in a server, cluster, or cloud.
- Domain model adopts domain driven design (DDD), interface and object oriented design.
Project address: gitee.com/mallfoundry…
conclusion
First, the example of “elephant in refrigerator” was used to illustrate the difference between process and object orientation, and then the example of “smart home system” was used to show that there may be some scripting coding problems in object-oriented programming. The examples “Elephants in refrigerators” and “Smart home Systems” lead to step-by-step object-oriented thinking.
Secondly, the passive and active relationship between releasing and walking is illustrated by the example of “elephant walking into refrigerator”. Finally, the error call (elephant.into()) is used to arouse people’s deep thinking on object modeling.