510 likes | 662 Views
Building Abstractions with Procedures (Part 1). CS 21a: Introduction to Computing I First Semester, 2013-2014. Last Time…. The basic building blocks of programming and basic ways of combining them Expressions and Statements The basic means of abstraction Variables. Today….
E N D
Building Abstractions with Procedures (Part 1) CS 21a: Introduction to Computing I First Semester, 2013-2014
Last Time… • The basic building blocks of programming and basic ways of combining them • Expressions and Statements • The basic means of abstraction • Variables
Today… • A first step in making systems modular instead of monolithic
Outline • Abstraction through Procedures • Procedure Calls and Environments • Procedural Programming In-Depth • Design by Contract
Consider the Following Program Fragment… intbanana_cost = number_of_bananas * cost_per_banana; intcoconut_cost = number_of_coconuts * cost_per_coconut; intapple_cost = number_of_apples * cost_per_apple; inttotal_cost = banana_cost + coconut_cost + apple_cost;
Some Observations… • Each fruit cost has been abstracted away. • The statement for the total does not need to concern itself with quantities and unit costs. • Later, we’ll see how iteration and recursion can expand this to arbitrarily many fruits. • Similarity of computing for banana_cost, coconut_cost, apple_cost
Abstraction through Procedures • The common process involved can be given a name. • Details can be hidden by just saying that the cost is a function of quantity and unit price. • This computational idea can be embodied in a procedure. staticintcost(int quantity, intunit_price) { return quantity * unit price; } parameters procedure definition The returnstatementis another kind of statement.
The Earlier Program Can Now Be Written As… intbanana_cost = cost(number_of_bananas, cost_per_banana); intcoconut_cost = cost(number_of_coconuts, cost_per_coconut); intapple_cost = cost(number_of_apples, cost_per_apple); inttotal_cost = banana_cost + coconut_cost+ apple_cost;
Another Example staticintsquare(int x) { return x*x; } public static void main(String args[]) { print(square(969));}
Is It Worth the Trouble? • A general rule has been discovered and written down. +1 for science. • The above example was simple, but if the procedure were more complicated… • Code becomes shorter and easier for humans to understand and maintain. +1 for humans. • Abstraction and modularity yields another advantage: reusability. Bonus +1 for engineers.
Is It Worth the Trouble? • The true power of this is that procedure definitions can have procedure calls within them, which we’ll get to later.
Anatomy of a Procedure Call intcoconut_cost = cost(number_of_coconuts, cost_per_coconut); procedure call arguments
Pass by Value • We say… • The value of number_of_coconutsis passed as an argument to the procedure call cost for the parameter quantity. • The value of cost_per_coconut is passed as an argument to the procedure call cost for the parameter unit_price.
Pass by Value • If some complicated expression were passed instead, the expression is evaluated first and the procedure call cares only about the resulting value. int foo = 2, bar = 15, deadbeef = 5; cost(2*3+4+6/foo, 12+bar/deadbeef-3); becomes, during the computation, cost(13, 12); before the procedure call proceeds. This is called applicative-order evaluation. But you don’t have to know that now.
Practice • Define the cost procedure as above. • Outside main, but inside the class • Call the cost procedure within the definition of main to calculate different costs. • Try to pass numbers as arguments. • Try to pass variables as arguments. • Try to pass expressions (with or without variables) as arguments.
Outline • Abstraction through Procedures • Procedure Calls and Environments • Procedural Programming In-Depth • Design by Contract
Different Procedure Calls Produce Different Environments • Each time cost was called… • A new table of name-value pairs was created. • quantity had a new, possibly different from before, value. • unit_price had a new, possibly different from before, value. • Each procedure call is executed in a context or environment independent from each other.
Different Procedure Calls Produce Different Environments main intnumber_of_bananas = 12, cost_per_banana = 3, number_of_coconuts = 5, cost_per_coconut = 15;
Different Procedure Calls Produce Different Environments main cost intbanana_cost = cost(number_of_bananas, cost_per_banana);
Different Procedure Calls Produce Different Environments main intbanana_cost = cost(number_of_bananas, cost_per_banana);
Different Procedure Calls Produce Different Environments main cost intcoconut_cost = cost(number_of_coconuts, cost_per_coconut);
Different Procedure Calls Produce Different Environments main intcoconut_cost = cost(number_of_coconuts, cost_per_coconut);
Different Procedure Calls Produce Different Environments • The collection of procedure calls in a computation (not in a program, not the written calls but the running calls) is called the procedure or method stack. • Each layer in the method stack has an environment associated with it. • When a procedure is called a new environment is created, and a new stack frame is pushed on to the method stack. • When the return statement of a procedure call is executed, the environment is destroyed, and the top stack frame is popped from the method stack.
Outline • Abstraction through Procedures • Procedure Calls and Environments • Procedural Programming In-Depth • Design by Contract
Monolithic versus Modular • Non-modular imperative • “Do this, then do this, …” • All in one big chunk • Modular imperative (also called procedural) • “Do this chunk, then do this chunk, …” • I’ll tell you how to break down the chunks into smaller chunks elsewhere. • Allows creation of layers of abstraction
Take Note • The procedure definition is not the same as the procedure call. • The procedure definition belongs to the program. • The procedure call is written in the program. • BUT each procedure call is like a request to do a computation. The written procedure call is part of the procedure definition (defining main), which is part of the program. The running procedure call is part of the computation.
Take Note • Parameters are not the same as arguments. • Parameters are variables. Arguments are values. • Even if you pass a variable as an argument, the variable has to be evaluated first before it is received by the procedure call. • As far as costis concerned, there is no coconut_cost or cost_per_coconutor fooor baror deadbeef. There is only the value for quantityand the value for unit_price. • Meaning you can also pass expressions as arguments
Take Note • The return statement is not the same as the return value.
Procedures Look Like Functions, But… • Is a valid mathematical function • But in no way says how to actually get y • It does suggest how to do it: try all possible y's, but that's not really possible to do with real numbers
Mathematical Functions Versus Algorithmic Procedures • Functions are what-is definitions. • Procedures are how-to definitions. • Sometimes the translation is trivial (square), sometimes not (square root) or there is a better way to compute it than suggested by the mathematical definition. • Or sometimes, there is no better way to do it (hard problems). • The functional programming paradigm attempts to unify the two.
Is Procedural Same As Functional? • Procedural is a special kind of imperative. • Functional is altogether different. • Because it expresses how-to definition in terms of what-is definitions, it is a special kind of declarative programming. • “This is, and this is,…” Oh, by the way, the computer can run it.
Question • Why is it possible to square(4); • But not to 4 * 4; ?
Question • Why is it possible to square(4); • But not to 4 * 4; ? Procedure calls are statements, but expressions are not. Expressions cannot be executed, only evaluated. This is not true of programming in general, but is an artefact of the imperative programming paradigm. In the first statement, the return value is simply ignored and can’t be used further in a computation because the algorithm contains no variable to refer to it.
Why Two Paradigms? • Imperative is closer to computer architecture, and is more powerful in terms of performance (better for computers). • Declarative is closer to mathematics, and is more powerful in terms of elegance and conciseness (better for science). • The split began in the 1950s, but the two are slowly merging today. Unfortunately, you will not learn the declarative styles of programming in this class.
Recommended Reading • “Revenge of the Nerds”, by Paul Graham. • But come back to this again after learning programming. • Don’t worry if you don’t understand everything here.
Practice Programming Problem: Interest Again • Rewrite the program you wrote for Alice so that it can potentially be used by Bob, who works as a financial adviser for several people and who might want to get several answers, not just using the same program, but in the same computation. • Simply, just make the program cleaner. • What procedures could you use here?
Note • At this point, our program doesn’t really allow Bob to do what he wants. • Later, we will see how to extend this program… • So that we can actually send Bob a ready-to-run program. • Receive any (but only one) input case and to give an answer for it with the same program (without changing the variable declarations and recompiling) • So that Bob can actually do abatch computation. • Receive an arbitrary number of input cases and to give an answer for each of them, not just with the same program, but also in the same computation
Outline • Abstraction through Procedures • Procedure Calls and Environments • Procedural Programming In-Depth • Design by Contract
Use Versus Definition • When you do this kind of abstraction, you are fulfilling two roles • The programmer working on the larger system who uses the procedure but exercises blackboxing (don’t care what goes on inside, as long as it gives the correct output for my correct input). • The programmer whose responsibility it is to make the black box work. • If you collaborate with other people, you may be required to fulfill only one of the roles at a time. Writing a procedure is like writing a new, smaller program embedded in the larger one. The larger algorithm delegates a part of the problem, or sub-problem to the procedure.
Wait What, There’s a Correct Input? • Part of the contract between the user and the implementer is that the user passes only the appropriate input values to the procedure. • The user has to call the procedure with the correct arguments, so that the procedure’s parameters have well-defined values. • All programs operate on the assumption that the input follows a specified format. • It is the user’s responsibility to not give invalid input. • But it is the implementer’s responsibility to handle unusual input, or special cases.
This Way, Programs Can Be Pipelined One After the Other • Like the direct sequencing of statements • Each statement/expression/procedure definition can be viewed as a mini-program. • Each statement execution/expression evaluation/procedure call can be viewed as mini-computation.
Design by Contract • Each module (procedure in this case) expects valid input, and is expected to return the correct output. • Each module is responsible for correctly solving a sub-problem. • Modules all have to follow their contracts, so that when they are tied together, they correctly solve the whole problem.
Note the Analogies • Procedure Definition • Procedure • (Running) Procedure Call • Parameter • Argument • Return Value • Program • Algorithm • Computation • Part of Algorithm • Part of Computation • Part of Computation • Problem • Problem Instance • Input Specs • Input • Output
Note the Analogies • Parameter Identifier • Parameter • Argument • Because really, a parameter is just a kind of variable • Variable Identifier • Variable • Value
Summary • Common patterns lead to abstraction. • Procedural abstraction is next step after variables. • Arguments are assigned to the parameters of a procedure call when values are passed to it (and only values are passed) . • A procedure call can return a value when the procedure definition contains a return statement. • Running procedure calls can be visualized with a method stack.
Summary • Functions are different from procedures. • Declarative (which includes functional) and imperative (which includes procedural) are the two main styles of programming.
Summary • Definition is not use. • Procedures are defined, then called. The two are not the same. • Procedural abstraction leads to blackboxing, which can only work through contracts between users and implementers.