Software Design Fall 2004 For today you should have read Chapters 4 and 5, and started on Homework 2. For next time: 1) Continue work on Homework 2. 2) Prepare for a quiz that will cover Chapters 2-5, emphasizing the vocabulary in the glossaries. 3) Sign up for the mailing list if you're not on it. Homework 1 Discussion --------------------- Two important ideas 1) interface design parameters and (later) return values preconditions and postconditions 2) finding an appropriate set of primitives This is the inverse problem of design by assembly! It can be iterative: a set of requirements leads to a set of primitives, which leads to expanded requirements. And now, a word from the masters: We have also obtained a glimpse of another crucial idea about languages and program design. This is the approach of statified design, the notion that a complex system should be structured as a sequence of levels that are described using a sequence of languages. Each level is constructed by combining parts that are regarded as primitive at that level, and the parts constructed at each level are used as primitives at the next level. The language used at each level of a stratified design has primitives, means of combination, and means of abstraction appropriate to that level of detail. - H. Abelson and G. Sussman "The Structure and Interpretation of Computer Programs" Three processes for discovering primitives: 1) planning and design 2) start with the concrete and generalize 3) start with "copy and paste" and refactor Parameters ---------- One way to make a function more general is to replace specific values with parameters. This function draws an O, but only for the turtle named bob: def draw_o(): fd(bob, 30) rt(bob) fd(bob, 60) rt(bob) fd(bob, 30) rt(bob) fd(bob, 60) draw_o() This function works for any turtle, but it's always the same size: def draw_o(t): fd(t, 30) rt(t) fd(t, 60) rt(t) fd(t, 30) rt(t) fd(t, 60) draw_o(bob) draw_o(yertle) draw_o(francesca_fiore) This function can make the letter any size: def draw_o(t, n): fd(t, n) rt(t) fd(t, 2*n) rt(t) fd(t, n) rt(t) fd(t, 2*n) draw_o(bob, 30) What other values might we think about replacing with parameters? Refactoring ----------- Now that the draw_o is appropriately general, we can look for places where a well-defined subfunction can improve the code. def half_o(t, n): fd(t, n) rt(t) fd(t, 2*n) rt(t) def draw_o(t, n): half_o(t, n) half_o(t, n) draw_o(bob, 30) If you haven't already, look over your solution to Homework 1 and see if you can find opportunities for refactoring. Homework 2 Discussion --------------------- Again, I want you to think about/discover the deep idea(s) the homework is intended to convey. 1) 2) 3) Stack diagrams -------------- 0) Initially, the stack has a frame called __main__ that contains global variables. 1) Whenever a function is called, it puts a new frame on the stack. 2) Function frames contain parameters and local variables. Draw a stack frame for the following program: def a(x, y): z = x + y b(z) def b(n): x = 2 * n c(x + 7) def c(n): y = 17 print n m = 3 n = 2 a(m, n) Some things to remember: 1) arguments are expressions 2) parameters are variables 3) parameter passing works by evaluating the arguments and assigning them to the parameters 4) parameters and local variables are local Stack diagrams are slightly more complicated when a function makes more than one function call. Think about that, and we will do an example next time. Recurtle the Turtle ------------------- On paper, sketch what you think this program will draw, then type in the code and try it. def draw(t, dist, n): if n==0: return fd(t, dist) lt(t) draw(t, dist, n-1) world.clear() bob = Turtle(world) draw(bob, 50, 4) Draw a stack diagram that shows the state of the program when n == 0.