Programming Philosophy
The origin of everything: problems and their solutions.
Programming is about solving problems, and problems can be solved with a variety of perspectives and ideas.
Worldview and Methodology.
Marx: the world is material and matter is in motion; matter in motion is universally connected and eternally developing.
Programming ideas and worldviews.
We know that the most fundamental opposition in the field of philosophy is the opposition between materialism and idealism, and attached to it, there are many oppositions, such as the opposition between metaphysics and dialectics, the opposition between gnosticism and agnosticism, etc. These oppositions form the basic system, schools and starting points of philosophy. In fact, these oppositions are all oppositions of worldviews. Worldview, in short, is how to see the world. The worldview is the origin and starting point of all philosophical problems.
Similarly, there are different worldviews in the procedural world. The most fundamental dichotomy is the dichotomy between process and object theory, which gives rise to two methodologies, process-oriented and object-oriented. So, to really understand process-oriented and object-oriented, we have to look deeper into these two worldviews in the program world.
The first thing to mention is that both process and object theories acknowledge that there are essentially only two things in the programming world - data and logic. Data, by nature, is static and constitutes the ontology and state of the program world; logic, by nature, is dynamic and acts on data to drive the evolution and development of the program world. Despite the unity of these views, the process and object theories have very different views on the forms of existence and evolution of data and logic.
Process theory holds that data and logic are separate and independent, each forming an aspect of the program world (Aspect). The so-called evolution of the world is a process in which the data make changes under the action of logic. This process has a clear beginning, end, input, and output, and each step has a strict cause-and-effect relationship. Processes are relatively stable, clear and predefined, and small processes are combined into large processes, and large processes can be combined into larger processes. Therefore, the program world is essentially process, with data as the process processing object, logic as the formal definition of the process, and the world as the totality of the individual processes going on continuously.
Object theory holds that data and logic are not separate, but interdependent. The relevant data and logic form individuals, which are called Objects, and the world is composed of one object after another. Objects have relative independence and provide certain services to the outside world. The evolution of the world is the interaction between objects through mutual invocation under some "initial force"; without the initial force, objects remain static. These interactions are not completely predefined and do not necessarily have a strict cause-and-effect relationship; interactions between objects are "accidental" and inter-object connections are "temporary". The world is composed of objects of all colors, and then under the initial force, the interaction between objects completes the evolution of the world.
Problems of software objects
the complexity of business logic.
the size of the software components.
the escalation of software complexity: one-dimensional linear (pure computation); two-dimensional flat (structural type of computation with business logic); three-dimensional: description of the complex real world.
In response to the escalation of software development tasks, there is a corresponding escalation process of programming ideas: the
Evolution of programming ideas.
1) computation-oriented: the driving force behind the emergence of computers with unique solutions.
2) process-oriented, structural: with finite solutions.
3) object-oriented: with infinite solutions.
Process-oriented programming and process-oriented problems.
The traditional process-oriented programming idea is summarized in eight words - top-down, progressive refinement! Implementation steps are as follows.
Describe the function to be achieved as a sequence of steps (process) in a step-by-step manner from the beginning to the end.
Complete these steps step by step, and if a step is more difficult, it can be refined again into a number of sub-steps, and so on, until the end to get the desired result.
The main body of the program is a function, a function is a module encapsulated to achieve a certain function, and the various sub-steps are often accomplished through each function, thus achieving code reuse and modular programming!
Problems.
1. Poor software reusability
Reusability refers to the same thing without modification or slightly modified can be reused many times the nature. Software reusability is one of the goals pursued by software engineering.
2. Software maintainability is poor
Software engineering emphasizes the maintainability of software, stresses the importance of documentation, and stipulates that the final software product should consist of complete and consistent configuration components. In the software development process, always emphasize the readability, modifiability and testability of the software is an important quality indicator of the software. Practice has proven that the software developed by traditional methods, its costs and fees are still very high when maintained, and the reason for this is poor modifiability and maintenance difficulties, resulting in poor maintainability.
3. The developed software does not meet the needs of users
The traditional structured approach to developing large software systems involves a variety of different areas of knowledge, and when developing systems with ambiguous requirements or dynamically changing requirements, the developed software systems often do not really meet the needs of the users.
Common methodology for all programming ideas (same as for other common problem solving).
Downscaling and then reassembling the problem.
It faces the problems of.
1) how to split into modules.
2) how to assemble these modules.
Physical level representation.
Files, classes, headers.
Logical level representation: modules, interfaces.
Abstraction, analysis and synthesis.
The corresponding strategies used are.
1) reducing the size of the objects faced during development.
2) reducing the complexity of the problem.
What is the work of software development?
The three transformations of software development.
1) transforming requirements into a program model.
2) transformation of the program model into code.
3) transformation of code into machine code.
Human-centeredness.
People are the key to transforming different forms of software
Decomposition to reduce complexity
The main features of design by decomposition are:
- Separation of duties (Seperation of Concerns, cf. Single Duty Principle) :Emphasis on functional separation.
- Focusing on interfaces (defining interactions): emphasizing the combination of modules.
Process-oriented programming
The core of structured programming thought: functional decomposition (top-down, layer by layer refinement).
Structured programming thought mainly divides a large problem into several small problems, and then divides several small problems into smaller problems. It is very difficult for us to solve large problems, but it is easier to solve the smallest problems after the division.
Procedural programming divides the programming task into steps and then executes them separately. Each of these steps is completed as if it were a single process within a task.
The core of object-oriented programming thinking: responding to change and improving reuse.
Object-oriented programming ideas are mainly reusability and flexibility (elasticity). Reusability is one of the main mechanisms of object-oriented programming. Flexibility is mainly a characteristic of coping with change, because the needs of customers are constantly changing, how to adapt to changes in customer needs, which is the problem of software design flexibility or elasticity.
The dual attributes of software.
1) tool attributes: the purpose of software is to give people to use, to achieve the function.
2) Engineering attributes: with engineering comes quality.
General strategies for software development.
People have proposed many approaches to software development in the decades of exploring software engineering methods, but none of them are rigorous theories. It is more important to learn to "choose the right method" and "generate new methods" than to apply them dogmatically.
There are three basic strategies in software development: reuse, divide and conquer, and optimization and compromise.
1. Reuse
For building a software system, reuse is the use of some developed software elements that are useful for building a new system to generate a new software system. In a new system, most of the elements are mature, and only a small part of the elements are innovative. In general, one can believe that what is mature is always more reliable, and that a large amount of mature work can be achieved quickly by reusing it. One should spend most of one's time on a small percentage of innovative work and a small percentage of one's time on a large percentage of mature work in order to get the work done both quickly and well.
We will have a certain degree of integration and can be reused software components called soft components (Software Component), software reuse is the direct use of existing soft components, can be assembled (or reasonably modified) into a new system, and can be done without having to start from scratch each time. On the one hand, the software reuse approach rationalizes and simplifies the software development process, reducing the total development effort and maintenance costs, both to reduce the cost of software and improve productivity. On the other hand, because the soft components are repeatedly used and validated, they have a high quality, so the new system composed of soft components also has a high quality.
2. Divide and conquer
Divide and conquer means to decompose a large and complex problem into several small and simple problems, and then solve them one by one. This simple idea comes from the experience of people's life and work, and is perfectly suitable for the technical field. Such as software architecture design, modular design are the concrete expression of divide and conquer.
3. Optimization and compromise
Software optimization refers to the optimization of software quality factors, such as improving the speed of operation, improve the utilization of memory resources, make the user interface more friendly, so that the three-dimensional graphics more realistic, etc.. We should establish the correct understanding that optimization is not something optional, but something that must be done.
By programming thinking, I mean the way of thinking that uses computers to solve people's practical problems.
This approach is reasonable when we do something like.
first dividing a problem into smaller modules, as if it were a book-to-chapter kind of relationship.
Dividing a small module into smaller parts, like this relationship from chapter to section.
eventually dividing them into indivisible parts, as in the relationship from sections to definitions and concepts.
This is like implementing the functionality of a program by considering the general direction first, and then implementing it step by step, so as not to overlap or miss anything.
The way we think when implementing the functionality of a program is
Holistic approach, determining the function we want to achieve, aligning the direction of thinking about the problem to the whole picture and the whole, starting from the whole picture and the whole, we have to determine the main contradiction in achieving this function at this point and make the appropriate trade-offs.
Structure method, determine the internal connection of the function, when conducting system thinking, pay attention to the rationality of the internal structure of the system. The system consists of parts, and whether the combination between parts and parts is reasonable has a great impact on the system. This is the problem of structure in a system. A good structure means that the parts that make up the system are well organized and organically connected with each other.
The elementary approach, which implements the constituent parts of the system one by one.
Booch was the first to describe the problems underlying the object-oriented approach to software development, pointing out that object-oriented development is a design approach that is fundamentally different from the traditional functional decomposition. Object-oriented software decomposition is closer to the human understanding of objective matters, while functional decomposition is obtained only through the transformation of the problem space.
Programming ideas, software engineering ideas, and the impact on other modules when changes are made within a module
What is object-oriented?
Object Oriented (Object Oriented) is to think and solve problems in a categorical way. The object-oriented way of thinking is suitable for dealing with complex problems. So, what do we mean by complex problems?
Complex often means "quite large in number". In philosophy, we have a saying that "quantity causes quality change". When the quantity reaches a certain level, there will be complex management problems. For example, if I ask someone to dinner tonight, it's a simple matter, I just need to pay attention to the whole process. However, if I ask 30,000 people to have dinner tonight. At this time, the primary problem is not the problem of each person eating, but the problem of how to deal with these 30,000 people? The most straightforward idea is to first sort the 30,000 people into categories: those who don't eat, those who drink porridge, those who eat vegetarian, those who eat meat, those who eat barbecue, etc. In this way, I can have the staff sorted into categories. In this way, I could let the staff sort out the various situations and deal with them in a reasonable manner.
This simple, uncomplicated classification idea is essentially object-oriented thinking. In turn, we find that this categorization idea is also a core concept of management.
The connection between process-oriented and object-oriented
Object-oriented cannot replace process-oriented, they are complementary. Object-oriented focuses on grasping the relationship between things at a macro level, but still uses a process-oriented way of thinking when it comes to specifying how to implement a particular detail.
Object-oriented how to leave the process-oriented, you can not achieve the real ground, become a source of water.
The nature of object-oriented and object-oriented programming language.
What is the essence of object-oriented? The answer is abstraction. From the face of the problem domain abstraction of the objects needed to solve the problem is the core idea of object-oriented approach. The ability to properly abstract enough object types, especially the abstraction of potential objects is the key to deciding whether the software design is good or bad. From a broader perspective, abstracting the complex problems we face, capturing the essence, and arriving at a highly refined logical model, is of great importance for problem solving. From this perspective, abstraction is not limited to the abstraction of objects, but also includes processes and higher-level system structures.
And object-oriented programming languages should provide support for realizing the object-oriented nature and features. When we say that a language is object-oriented, we are actually providing support for the object-oriented software it is intended for. Therefore, there is no necessary connection between C++'s virtual functions, multiple inheritance, and object-orientation, but rather the language's choice of means to support polymorphism and inheritance.
Programming paradigms refer to the basic style or paradigm of computer programming.
To borrow a philosophical term, if each programmer is creating a virtual world, then the programming paradigm is the worldview and methodology they consciously or unconsciously adopt in it. As we know, programming is about solving problems, and there are various perspectives and ideas for solving problems, among which the universal and proven patterns are summarized as paradigms. For example, we commonly use "object-oriented programming" as a paradigm.
Due to the different focus and way of thinking, the corresponding paradigms naturally have their own focus and tendencies, so some paradigms are often described by the term 'oriented'. In other words, each paradigm leads people to analyze and solve problems with a certain tendency, which is not "orientation"?
If we compare a programming language to a weapon, its syntax, tools and techniques are the moves, and the programming paradigm it uses is the mind. The programming paradigm is abstract and must be reflected in a concrete programming language. The worldview it represents is often embodied in the core concepts of the language, and the methodology it represents is often embodied in the expression mechanisms of the language. A paradigm can be implemented in different languages, and a language can support multiple paradigms at the same time.
What is the complexity of software design
One of the missions of software technology development is to control complexity (Complexity). From the creation of high-level languages, to structured programming, to object-oriented programming, to component-based programming, and so on. The Many Faces of Complexity in Software Design is not uniformly defined, so if you want to know more about it, read The Many Faces of Complexity in Software Design.
There are subtle differences between Complex and Complicated in English. But to summarize, software complexity has a negative meaning and includes two main points:
Difficult to understand (difficult to maintain and extend.)
Unpredictable behavior
Complexity is inevitable as software grows in size. It is a relative concept in itself, and the same system has different levels of complexity for the designer, developer, and maintainer. The complexity that a programmer can master varies from time to time, and it is the goal of a programmer to continuously improve.
Since the industry has been fighting complexity for decades, let's sort it out.
Reducing complexity with decomposition
The main features of design by decomposition are:
- Separation of duties (Seperation of Concerns, cf. Single Duty Principle)
- Focus on interfaces (defining interactions)
This is the most commonly used technique. A large problem is constantly broken down into smaller problems for analysis and research, and then put together again. In the West, this is called the Divide and Conquer Principle.
In the era of structured programming, modularization is advocated. The first engineers to propose software complexity proposed Component Based Software (CBS). I don't know if it was inspired from Lego blocks to split the system into different components, implement them individually, and then assemble them together.
In architecture design, whether it is C/S style, layered, or N-Tier, SOA, and the previous component style, all are in decomposition, they are more emphasis on the combination of interaction. The design is to divide the responsibilities, define the interfaces, and then develop them individually. Then the interaction will be limited to the interface layer, you can well control the complexity of the whole system.
For example, if the application layer uses a speech library (Speech Library, a modular application in the form of a library), it is not necessary to care about its internal implementation, just to understand how to use its API.
From structured design to object-oriented programming
As time goes by, software development projects are becoming more and more complex. Although process-oriented programming has many advantages, its disadvantages are gradually revealed when it is used to solve complex problems: in process-oriented programming, data and operations are separated from each other, which leads to the fact that if the structure of the data changes, the corresponding operation functions have to be rewritten; if the requirements change or new requirements are encountered, it may also involve the redistribution of modules, which requires In case of requirement changes or new requirements, it may also involve the reallocation of modules, which requires a large number of modifications to the originally written functional modules. The separation of data and operations in process-oriented programming makes some modules closely integrated with the specific application environment, and it is difficult to reuse the old modules in the new program. These inherent shortcomings of process-oriented programming ideas make it more and more unable to adapt to the development of large-scale software projects, which is really "process-oriented, also process-oriented".
It is better to go back to the programming languages and see how they grew up step by step. In the C language before the introduction of various languages, the industry called them "step-by-step" language. The so-called "step-by-step" languages were characterized by a linear process of events, but not the changes that could occur, and by an emphasis on the linkage of steps, while ignoring the substitutability and replaceability of steps.
The creation of C solves this problem of "planning over change" to a certain extent, because it allows similar events or steps to be written as replaceable and shareable "modules" (Module).
But the "modular" approach to programming does not address the root of the problem. It is easy to see that both "step-by-step" and "modular" languages see the world as a linear plane, with only one dimension of programming: time. Inspired by the development of databases from data storage fields to relational databases and then multidimensional databases in the 1980s and 1990s, computer languages also began to change their thinking and further reform their languages to make them flexible, three-dimensional, easy to construct and highly applicable, so the concept of "class" emerged.
The idea of "class" is to bring things together, to bundle data, functions and behavioral methods, to restrict access to them, and to increase adaptability.
Alpha Dog uses two "neural networks": strategy and value, to build an infinitely stretching "Monte Carlo tree" of future variations at each move of the game, searching for moves that have a higher chance of winning, rather than focusing on immediate benefits. Since it is difficult for human players to calculate results beyond a hundred moves in a limited time, fast computation and robust selection based on a large number of parameter variables is the best way for robots to win. This neural network approach, which I also used when I worked for an artificial intelligence company in the mid-1990s, we used the same calculation method used by an American physicist to perform thermonuclear fusion.
Structured design :
The structured programming approach advocates analyzing system requirements by function, with principles such as top-down, stepwise improvement, modularity, etc.
Object-oriented and philosophy
Everything in a system is an object; an object is a wrapper around properties and their operations; objects can be divided into classes according to their nature, and objects become instances of classes; instance and inheritance relationships are static relationships between objects; message passing is the only form of dynamic connection between objects, and the only form of computation; methods are sequences of messages.
From the perspective of worldview, it can be argued that: the basic philosophy of object-oriented is that the world is composed of a variety of objects with their own laws of motion and internal states; the interaction and communication between different objects constitute the complete real world. Therefore, one should understand the world as it is, and reflect the world directly through objects and their interrelationships. The system thus established can conform to the real world as it is.
"Worldview, meaning 'looking above the world,' is the general and fundamental view of the world. The starting point and origin of any philosophical question is the question of worldview. What kind of worldview determines what kind of philosophical viewpoint. -- Marx"
Seeing the world
As we know, in the field of philosophy, the most fundamental opposition is the opposition between materialism and idealism, and under it, there are many oppositions, such as the opposition between metaphysics and dialectics, the opposition between gnosticism and agnosticism, and so on. These oppositions form the basic system, schools and starting points of philosophy. In fact, these oppositions are all oppositions of worldviews. Worldview, in short, is how to see the world. The worldview is the origin and starting point of all philosophical problems.
Similarly, there are different worldviews in the procedural world. The most fundamental dichotomy is the dichotomy between process and object theory, which gives rise to two methodologies, process-oriented and object-oriented. So, to really understand process-oriented and object-oriented, we have to look deeper into these two worldviews in the program world.
The first thing to mention is that both process and object theories acknowledge that there are essentially only two things in the programming world - data and logic. Data, by nature, is static and constitutes the ontology and state of the program world; logic, by nature, is dynamic and acts on data to drive the evolution and development of the program world. Despite the unity of these views, the process and object theories have very different views on the forms of existence and evolution of data and logic.
Process theory holds that data and logic are separate and independent, each forming an aspect of the program world (Aspect). The so-called evolution of the world is a process in which the data make changes under the action of logic. This process has a clear beginning, end, input, and output, and each step has a strict cause-and-effect relationship. Processes are relatively stable, clear and predefined, and small processes are combined into large processes, and large processes can be combined into larger processes. Therefore, the program world is essentially process, with data as the process processing object, logic as the formal definition of the process, and the world as the totality of the individual processes going on continuously.
Object theory holds that data and logic are not separate, but interdependent. The relevant data and logic form individuals, which are called Objects, and the world is composed of one object after another. Objects have relative independence and provide certain services to the outside world. The evolution of the world is the interaction between objects through mutual invocation under some "initial force"; without the initial force, objects remain static. These interactions are not completely predefined and do not necessarily have a strict cause-and-effect relationship; interactions between objects are "accidental" and inter-object connections are "temporary". The world is composed of objects of all colors, and then under the initial force, the interactions between objects complete the evolution of the world.
Process-oriented programming is oriented to the process of problem solving.
The traditional process-oriented programming idea is summarized in eight words - top-down, step-by-step refinement! The implementation steps are as follows.
Describe the function to be achieved as a sequence of steps (process) in a step-by-step manner from the beginning to the end.
Complete these steps step by step, and if a step is more difficult, it can be refined again into a number of sub-steps, and so on, until the end to get the desired result.
The main body of the program is a function, a function is a module encapsulated to achieve a certain function, and the various sub-steps are often accomplished through the various functions, thus achieving code reuse and modular programming!
Process-oriented programming is a programming method to think and organize in a function-centered way, which emphasizes the process of processing and handling the data of the system. In programming, the main function or process is the basic organization of the program, and the system function is composed of a set of related processes and function sequences.
Abstraction of objects and abstraction of relations
Process-oriented design is more challenging and skillful, object-oriented mainly lies in the technical nature of object abstraction, and once the abstraction is completed
In summary.
Object-oriented is a high degree of abstraction of things.
Process-oriented is a top-down programming
Object-oriented must first build an abstract model, and then just use the model directly.
Object-oriented: use linear thinking. Complementary to process-oriented. In the software development process, on a macro level, use object-oriented to grasp the complex relationships between things and analyze the system. At the micro level, process-oriented is still used.
"Process-oriented" is an event-centered programming mindset. It means analyzing the steps needed to solve a problem, and then using functions to implement these steps and call them in sequence.
Engineering Metaphors
Among the various metaphors, construction engineering is the most closely related to software development, and this metaphor has the most similarities to software development and therefore the most profound impact. This metaphor has four main points: decomposition, distribution, design, and staging.
Decomposition is an extremely profound idea of dividing the whole process into phases, breaking the whole task into subtasks, breaking the system into multiple levels, multiple modules, dividing requirements into types, etc. Such thinking is the only correct way to solve complex problems; a mess of requirements, tasks, projects, and designs simply cannot succeed. But decomposition also means it better be divided right the first time, when tasks are decomposed in layers into many, many subtasks, modules, submodules, classes. You find that there is a problem with the decomposition of one subtask, and the difficulty of modifying it can be extremely staggering, whereas with software development, it is almost never the case that the division is correct the first time.
Distribution, like decomposition, is unique to the engineering metaphor. When a system needs to be completed, after it has been carefully decomposed, the granularity of the decomposition will be such that a person can complete it independently, and then it will be reasonably distributed to people with different abilities and strengths based on the available resources and the back-and-forth dependencies of the tasks. Without such an allocation, the project would also be in chaos, and the metaphor also contains a kind of (domination relationship), the existence of assigned people and assigned people, layer by layer decomposition of tasks and layer by layer decomposition of human resources, making the whole project a tight pyramid structure, and such a structure, often making the project's resilience and possibilities, as the project expands and shrinks.
Based on the above two points, the engineering metaphor is extremely logical to introduce the conclusion that "changes in requirements must be strictly controlled and, if possible, all changes must be topped back." In pure software engineering thinking, any change in requirements is unwelcome.
Design is extremely important, both for architecture and for software development. But design is different from design. In architecture, a building that doesn't reflect the designer's vision is called a "concrete block" without a soul. But in software development, if the developer is always trying to add his own stuff to the program, it is called over-design. But because software development mimics architectural engineering, over-design becomes common.
In construction engineering, there is an extremely clear division of phases, analysis, design, construction, and acceptance. The earliest software engineering was executed in exact imitation of such phases. The consequences of such imitation were serious, because such phases were not characteristic of software development, and most of them failed when they were forcibly applied. Subsequent improvements always seemed to jump out of this mindset, like fitting a curve with countless straight lines, and using more than N squares to spell out a circle. For example, spiral development, in a spiral, but also to engage in four quadrants, making the process of software development, constantly retrace these four stages. But is the process of software development, really like construction work?
Dancing Metaphors
CMM itself does not need metaphors, its theoretical foundation comes from pure software engineering, all software engineering related metaphors, CMM can be used, but CMM has its own characteristics, mainly in the implementation of CMM. I have seen a metaphor about CMM implementation: software development is like dancing, software process improvement is like choreography, software developers in the process improvement experts know, like dancers in the choreographer's knowledge, learn new rhythms, movements. Finally, the software product that satisfies the consumer is developed. Just like a dancer delivers an outstanding performance to the audience. Such a metaphor opens the way to a huge consulting market; the most talented dancer cannot do without the choreographer's knowledge, so if you want your company to improve its CMM rating, you must get an expert to do the consulting... clever indeed! But such a metaphor does not stand up to scrutiny. In the process of choreography, the actors rehearse with the goal of meeting the choreographer's requirements, and if the performance is not good, the choreographer is naturally responsible. But the improvement of the software development process, if also to win the satisfaction of the consulting experts, when the software is developed out of the money, those experts will not be responsible. They would have earned their consulting fees and left long ago. The key problem is that process improvement can only be a means to an end, it cannot be an end in itself, and it cannot be taken for granted that a perfect process will bring a perfect product. A choreographer is not an audience, and no choreographer can guarantee that his or her creation will be well received by the audience, but why do CMM experts now dare to make such a guarantee? When a dancer falls perfectly on a "triangular stage", who will be responsible for such a tragedy?