CSC/ECE 517 Fall 2011/ch1 1e aa
Wiki Chapter: CSC/ECE 517 Fall 2011/ch1 1e aa
Brief Background on the Programming Paradigms
Programming Paradigms forms the fundamental basis of the style in which we code. Paradigms define the way the code is structured aesthetically. Different paradigms differ in the way in which a language defines its concepts about the way to represent the code elements i.e. variables, functions, objects etc. and the way in which computation of the code takes place. Thus, any paradigm acts as a structure or set of rules on which that language is based. This provides the programmer with set of principles which are to be obeyed when the language is used.
There are many different programming paradigms which are developed over the years. Each one offers something different than the others and many are considered much better over the others. Another flavour to paradigms is that some languages can support more than one paradigms. This gives the programmer the choice of how to use the elements of different paradigms in his own discretion.
In this article, we focus on two programming paradigms: Block-Structured programming and Object-Oriented Programming.
Introduction
This Wiki chapter talks about the basic fundamentals of two programming paradigms; block structured programming and Object Oriented programming and explains the advantages of Object Oriented programming over block structured programming which made O-O languages more common and widely used in the Software Industry today. We also focus on the practicability of using block structured approach in O-O languages.
Block-Structured Languages
A Block is a part of code that is clustered together. It is thus; a group of program statements and variables referred to in those statements. Block of code always begins with variable declarations and is followed by procedural declarations, is always contained within delimiters; typically begin-end, opening and closing curly braces '{ }' and can be compiled and executed as a single execution unit. Block can be the body of a subroutine, a function or an entire program. The main block can contain subsections consisting of inner blocks. Those inner blocks can contain more inner blocks giving rise to a nested block structure. Typically, Nesting can be repeated to any depth required. One example of a language which allows such block structure is Pascal[1].
program a; var id1, id2, id3 : integer; { program a declarations } procedure b; var id1 : integer; { procedure b declarations } procedure c; var id2 : integer; { procedure c declarations} begin { Beginning of c's statement part } id2 := id1; end; begin { Beginning of b's statement part } id1 := id3; id2 := id1; end; begin { Beginning of main program's statement part } id1 := id2; end.
In most primitive block structured languages, the scope of a variable can be limited to the block in which it is declared. This is called lexical scoping. Thus, referring to the nested structure of the blocks; all the variables declared in the outer block can be accessed within that block and all of its inner blocks but are not accessible outside that block. Additionally, values of the variables in the outer blocks are accessible in the inner blocks if and only if there is no other variable in the inner block with the same name. This duplicate declaration of variables is called Shadowing.
By having statements grouped together as a Block allows us to treat it as a single statement and thus allows the programmer to keep the 'lexical' scope of the functions, variables and procedures closely bound to that Block. Earliest block-structured languages were Algol 58 and Algol 60 with which the initial idea of block was born.
Important Aspects of Block-Structured Programming
Relation of Block-Structured Programming to Structured Programming
There is a subtle relation between block programming and structured programming. Structured programming encompasses majority of the fundamentals of block programming paradigm. Most of the block-structured languages fall under the structured programming paradigm for example: Algol, Pascal. In essence, structured programming employs a hierarchical approach in which the main problem is broken down into different smaller modules. Thus, it breaks down a bigger task into smaller ones and therefore solving the smaller tasks leads to indirectly solving the actual problem.
The important thing to note here is that such programs always have a single point of entry and often have single points of exit. The modules in this paradigm are independent of each other and thus; are blocks of code where the scope is limited to that particular module. Structured Programming normally imply simple hierarchical flow structures consisting of sequence (execution of statements in particular order), selection (some selection criteria) and iteration (repetition until the program reaches a certain state).
Features of Block-Structured Programming
- Structured programming is task-centric
- Applies a top-down approach of problem solving.
- It is a straight forward programming approach with a pre-defined flow.
- Programs have a modular design structure.
- Employs an approach of bringing data which is to be operated upon to the functions or methods.
- Most often; such programs have a single point of entry and single point of exit.
- Allows the programmer to keep the program within his intellectual grasp due to its modular design and limited variable scope.
- Programs have data-structures with a limited scope.
- Programs allow limited control structures.
- Simplicity in Writing Code: It is extremely easy to write code in a block structured language. Modularity is the prime reason due to which programmers can concentrate on various aspects of the program and design their code in the most efficient way. The concept of single point of entry also allows the programmer to better design their code in a heirarchial strucuture and thus create a better solution. Easiness in writing code amounts to saving precious time. If written efficiently, procedures can also be used in other programs requiring the same functionality.
- Debugging made easy: Modular structure provides the progammer to isolate bugs easily. As each procedure does only one particular task, it is easy to debug individually. Programmer can recognize the errors by simply narrowing it down to the procedure which is faulty. Additionally, each procedure in the modular design has a single point of entry i.e. through any other procedure. This makes it easy to write and use Stubs for testing individual procedures before they are used or integrated into the main program. Stubs are dummy procedures which provide test data to the procedures.
- Understandability of Code: It is extremely easy to look at procedures and figure out the entire modular structure of the program. Each procedure and variables have meaningful names which make it much lucid and easy to understand. Morever, the scope of the variables in the procedure is often limited to that procedure itself which adds to the simplicity of figuring what that variable is used for.
- Modification made simple: Due to all the above properties of a block structured program, any programmer looking at code written by some other programmer can easily understand and thus modify it with least effort. Additionally, if the specifications of the program change later, changes to it can be made easily.
- Top-down design approach focuses more on the design of sequence of instructions required for the solution. Design of data-structures which is also an integral part of designing the solution to the problem is outside the scope of the top-down design approach.
- As data is to be passed to the methods; there is no encapsulation. A better approach is keeping data as it is and declaring the necessary funcitons near the data.
- There is no information hiding concept in structured programming. The concept of lexical scope applies but is not equivalent to information hiding or encapsulation.
- Top-down design approach does not suit all type of problems. If we cannot determine the sequence of instructions in advance, structured programming cannot be applied for that problem.
- The modular design of structured programming poses a very big problem. By dividing the problem into seperate methods/functions, it limits the usability of those functions to only that problem or problems of the specific genre. These modules/methods cannot be used easily into other problems. Use of such modules will require serious re-design and effort.
Object-Oriented Programming
Object-oriented programming (OOP) is a programming paradigm which focuses on objects instead of actions and data instead of logic. Historically, a program has always been viewed as a logical sequence of instructions that takes the input, processes it, and produces the output. Due to this focus, the programming challenge has always been the logical sequence, rather than defining data.
Whereas, OOP takes the focus away from the procedure. It represents data from the real world (called as objects) which we really want to manipulate rather than the logic required to manipulate them. These objects could range from human beings to buildings to widgets on your desktop. Thus the first step of OOP is data modeling which includes identifying objects and the relations amongst them. Once the identification of the objects is done, these objects are then generalized into classes of objects and define the kind of data it contains and any logic sequences that can manipulate it. Each distinct logic sequence is known as a method. Objects are real instances of a class. The programmer communicates with objects and they communicate with each other with well-defined interfaces called messages.
While Simula was the first object-oriented programming language, the most popular OOP languages used today are Java, Python, C++, Visual Basic .NET and Ruby. Although many languages claim to be solely object oriented, most of the time that is not the case. There are some languages that are purely o-o ,while others are hybrid. Now, a language must capture several qualities for it to be purely O-O. These qualities are:
- Encapsulation/Information Hiding
- Inheritance
- Polymorphism/Dynamic Binding
- All pre-defined types are Objects
- All operations performed by sending messages to Objects
- All user-defined types are Objects
Below is an small example of Object-Oriented Programming in Java:
class A {
int x;
int y;
int get(int p, int q){
x=p; y=q; return(0);
}
void Show(){
System.out.println(x);
}
} // end of Class A
class B extends A{
public static void main(String args[]){
A a = new A();
a.get(5,6);
a.Show();
}
void display(){
System.out.println("B");
}
} // end of Class B
Pure O-O languages satisfy all the above qualities, whereas, hybrid languages support some of these. Typically, many languages support first three qualities, but not the last three. Some examples of pure O-O languages are Eiffel, Smalltalk, and Ruby.
Many think of Java as a pure Object-Oriented language, but by its inclusion of "basic" types that are not objects, it fails to meet the fourth quality. Also it fails to meet quality five by implementing basic arithmetic as built-in operators, rather than messages to objects. C++ supports multiple paradigms, O-O being one of them. Thus it is not a pure oo language. Another seemingly object oriented language, Python is actually a multi-paradigm supporting language. At times, o-o concepts seem to be fixed up in it. Some operations are implemented as methods, while others are implemented as global functions. The self parameter adds to its awkwardness.
Ruby on the other hand, is a scripting language which was created as a reaction to Python and Perl. The designers of Ruby wanted a language that was stronger than Perl and more object oriented than Python. Visual Basic and Perl are both procedural languages that have had some Object-Oriented support added on as the languages have matured.
Features of Object-Oriented Programming
What makes O-O better?
Block-structure in O-O programming
Comparison in a Nutshell
Let us compare both the programming paradigms with respect to different points which brings out a strong distinction between the two.
Point of Comparison | Block-Structured Languages | Object-Oriented Languages |
---|---|---|
Primary focus | Focus on finding the sequence of instructions necessary to solve the problem. Design of the necessary data-structures is out of scope. | Focus on identifying and representing the problem in terms of an 'object' which has its own data, sub-routines and state. Different objects in the problem interact by sending messages to each other and thus result in change in its internal state. The final state and values of the objects refer to the solution. |
Problem Solving Approach | Primarily Top-down design | Identification and design of necessary objects. Close to being 'better models of the way the world works'. |
Program Flow | Often sequential with program having single point of entry and exit. | Complex program flow. Can sometimes depend on the internal state of the objects. |
Modularity | Limited modularity. Program is divided into modules or per say procedures independent of each other but are constrained due to uniqueness to that particular problem. | Extremely modular due to the presence of objects which contain their own data and sub-routines. |
Data Protection/Hiding | No concept of data-hiding. Variables local to one method cannot be accessed by other method. But, Global variables can be accessed anywhere within the program. | One of the main fundamentals of O-O languages. Access specifiers like 'public', 'private' and 'protected' dictate the rules of data-hiding. Data which is private is confined to one object and cannot be directly changed by any other method except its own. This places the responsibility of managing data with the object itself This is called as ownership. Thus, data can be accessed ( read/write/modified ) only through the object's own interfaces. |
Ease of Understanding | Smaller programs are easy to understand but as the program increases in size; understanding is a struggle. | Easy to understand due to its real world-like design and flow. |
Reuse of Code | Limited or no re-usability. | Highly re-usable code as the code developed can be easily modified or extended to suit a problem's need. |
Support for declaring new data types | Extremely difficult as no in-built functionality exists. | Easily possible due to the concept of classes. Generic classes can be built as per the required specifications. |
Efficiency | Efficient for solving small problems. | Efficient for solving large problems which have a complex structure and require complex data-types, abstraction and data-security. |
Maintenance | Maintenance is easy for smaller programs but can consume a-lot of effort for larger program size as it requires the programmer to know and understand the dependencies of every module in the program. This makes it difficult to debug and test the program. | Extremely simple as O-O languages aim for high modularity. Secondly, programmer is not concerned with the details of how the data is stored and represented. Thirdly, they also tend to keep low coupling which makes it easy to debug and test different modules in the program. |
Extensibility | Less Extensible as modules developed need to be re-organised and re-structured heavily in order to meet different needs. | High extensibility is one of the most important advantages of OOP. Code can be easily modified and 'plugged-in' to a different program. Methods can be exteneded due to many properties such as polymorphism, inheritance and support for multiple inheritance through interfaces. |
Flexibility | Less flexible. Sometimes, certain problems do not fit into the 'top-down design' approach. | High flexibility. The modelling of problems into world-like objects makes it easy to solve any practical problem. |
Examples | C, Pascal, Algol 50, Algol 60 | C++, Java, Ruby, Python. |