Building Abstractions with Procedures (Part 1) CS 21a: Introduction to Computing I First Semester, 2013-2014.

  • Published on
    16-Dec-2015

  • View
    212

  • Download
    0

Transcript

<ul><li> Slide 1 </li> <li> Building Abstractions with Procedures (Part 1) CS 21a: Introduction to Computing I First Semester, 2013-2014 </li> <li> Slide 2 </li> <li> Last Time The basic building blocks of programming and basic ways of combining them Expressions and Statements The basic means of abstraction Variables </li> <li> Slide 3 </li> <li> Today A first step in making systems modular instead of monolithic </li> <li> Slide 4 </li> <li> Outline Abstraction through Procedures Procedure Calls and Environments Procedural Programming In-Depth Design by Contract </li> <li> Slide 5 </li> <li> Consider the Following Program Fragment int banana_cost = number_of_bananas * cost_per_banana; int coconut_cost = number_of_coconuts * cost_per_coconut; int apple_cost = number_of_apples * cost_per_apple; int total_cost = banana_cost + coconut_cost + apple_cost; </li> <li> Slide 6 </li> <li> 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, well see how iteration and recursion can expand this to arbitrarily many fruits. Similarity of computing for banana_cost, coconut_cost, apple_cost </li> <li> Slide 7 </li> <li> 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. static int cost(int quantity, int unit_price) { return quantity * unit price; } parameters The return statement is another kind of statement. procedure definition </li> <li> Slide 8 </li> <li> The Earlier Program Can Now Be Written As int banana_cost = cost(number_of_bananas, cost_per_banana); int coconut_cost = cost(number_of_coconuts, cost_per_coconut); int apple_cost = cost(number_of_apples, cost_per_apple); int total_cost = banana_cost + coconut_cost + apple_cost; </li> <li> Slide 9 </li> <li> Another Example static int square(int x) { return x*x; } public static void main(String args[]) { print(square(969)); } </li> <li> Slide 10 </li> <li> 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. </li> <li> Slide 11 </li> <li> Is It Worth the Trouble? The true power of this is that procedure definitions can have procedure calls within them, which well get to later. </li> <li> Slide 12 </li> <li> Anatomy of a Procedure Call int coconut_cost = cost(number_of_coconuts, cost_per_coconut); arguments procedure call </li> <li> Slide 13 </li> <li> Pass by Value We say The value of number_of_coconuts is 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. </li> <li> Slide 14 </li> <li> 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 dont have to know that now. </li> <li> Slide 15 </li> <li> 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. </li> <li> Slide 16 </li> <li> Outline Abstraction through Procedures Procedure Calls and Environments Procedural Programming In-Depth Design by Contract </li> <li> Slide 17 </li> <li> 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. </li> <li> Slide 18 </li> <li> Different Procedure Calls Produce Different Environments IdValue number_of_bananas12 cost_per_banana3 number_of_coconuts5 cost_per_coconut15 main int number_of_bananas = 12, cost_per_banana = 3, number_of_coconuts = 5, cost_per_coconut = 15; </li> <li> Slide 19 </li> <li> Different Procedure Calls Produce Different Environments main cost IdValue quantity12 unit_price3 int banana_cost = cost(number_of_bananas, cost_per_banana); </li> <li> Slide 20 </li> <li> Different Procedure Calls Produce Different Environments IdValue number_of_bananas12 cost_per_banana3 number_of_coconuts5 cost_per_coconut15 banana_cost36 main int banana_cost = cost(number_of_bananas, cost_per_banana); </li> <li> Slide 21 </li> <li> Different Procedure Calls Produce Different Environments main cost IdValue quantity5 unit_price15 int coconut_cost = cost(number_of_coconuts, cost_per_coconut); </li> <li> Slide 22 </li> <li> Different Procedure Calls Produce Different Environments IdValue number_of_bananas12 cost_per_banana3 number_of_coconuts5 cost_per_coconut15 banana_cost36 coconut_cost75 main int coconut_cost = cost(number_of_coconuts, cost_per_coconut); </li> <li> Slide 23 </li> <li> 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. </li> <li> Slide 24 </li> <li> Outline Abstraction through Procedures Procedure Calls and Environments Procedural Programming In-Depth Design by Contract </li> <li> Slide 25 </li> <li> Monolithic versus Modular </li> <li> Slide 26 </li> <li> 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, Ill tell you how to break down the chunks into smaller chunks elsewhere. Allows creation of layers of abstraction </li> <li> Slide 27 </li> <li> Without Procedures, Imperative Programs Look Like This Open Hand Put Hand Next to Spoon Close Hand Move Hand Till Spoon Touches Food </li> <li> Slide 28 </li> <li> With Procedures, Imperative Programs Look Like This Eat Put Food in Mouth Grab Spoon Open Hand Put Hand Next to Spoon Close Hand Scoop Food Put Spoon in Mouth Take Spoon Out, Leaving Food In Chew Move Jaw Up Move Jaw Down Repeat Swallow </li> <li> Slide 29 </li> <li> 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. </li> <li> Slide 30 </li> <li> 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 cost is concerned, there is no coconut_cost or cost_per_coconut or foo or bar or deadbeef. There is only the value for quantity and the value for unit_price. Meaning you can also pass expressions as arguments </li> <li> Slide 31 </li> <li> Take Note The return statement is not the same as the return value. </li> <li> Slide 32 </li> <li> 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 </li> <li> Slide 33 </li> <li> 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. </li> <li> Slide 34 </li> <li> 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. </li> <li> Slide 35 </li> <li> Question Why is it possible to square(4); But not to 4 * 4; ? </li> <li> Slide 36 </li> <li> 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 cant be used further in a computation because the algorithm contains no variable to refer to it. </li> <li> Slide 37 </li> <li> 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. </li> <li> Slide 38 </li> <li> Recommended Reading Revenge of the Nerds, by Paul Graham. Revenge of the Nerds But come back to this again after learning programming. Dont worry if you dont understand everything here. </li> <li> Slide 39 </li> <li> 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? </li> <li> Slide 40 </li> <li> Note At this point, our program doesnt really allow Bob to do what he wants. Later, we will see how to extend this program 1. 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) 2. So that Bob can actually do a batch 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 </li> <li> Slide 41 </li> <li> Outline Abstraction through Procedures Procedure Calls and Environments Procedural Programming In-Depth Design by Contract </li> <li> Slide 42 </li> <li> 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 (dont 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. </li> <li> Slide 43 </li> <li> Wait What, Theres 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 procedures parameters have well-defined values. All programs operate on the assumption that the input follows a specified format. It is the users responsibility to not give invalid input. But it is the implementers responsibility to handle unusual input, or special cases. </li> <li> Slide 44 </li> <li> 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. </li> <li> Slide 45 </li> <li> 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. </li> <li> Slide 46 </li> <li> Note the Analogies Procedure Definition Procedure (Running) Procedure Call Parameter Argument Return Value Program Algorithm Computation Part of Algorithm Part of Computation Problem Problem Instance Input Specs Input Output </li> <li> Slide 47 </li> <li> Note the Analogies Parameter Identifier Parameter Argument Because really, a parameter is just a kind of variable Variable Identifier Variable Value </li> <li> Slide 48 </li> <li> 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. </li> <li> Slide 49 </li> <li> Summary Functions are different from procedures. Declarative (which includes functional) and imperative (which includes procedural) are the two main styles of programming. </li> <li> Slide 50 </li> <li> 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. </li> <li> Slide 51 </li> <li> Next Time More Combinations through Procedures Walls can be built with bricks, and cities can be built with walls. Procedural Programming In-Depth </li> </ul>

Recommended

View more >