Readability [Skrien 4.0] Programs must be written for people to read, and only incidentally for machines to execute.

Similar documents
a correct statement? You need to know what the statement is supposed to do.

Violations of the contract are exceptions, and are usually handled by special language constructs. Design by contract

Assertions, pre/postconditions

Why Design by Contract! CS 619 Introduction to OO Design and Development. Design by Contract. Fall 2012

Assertions. Assertions - Example

References: internet notes; Bertrand Meyer, Object-Oriented Software Construction; 10/14/2004 1

3. Design by Contract

Design by Contract in Eiffel

6.170 Lecture 6 Procedure specifications MIT EECS

AXIOMS OF AN IMPERATIVE LANGUAGE PARTIAL CORRECTNESS WEAK AND STRONG CONDITIONS. THE AXIOM FOR nop

Lecture 1 Contracts : Principles of Imperative Computation (Fall 2018) Frank Pfenning

Comparing procedure specifications

Classes, interfaces, & documentation. Review of basic building blocks

MSO Lecture Design by Contract"

Lecture 1 Contracts. 1 A Mysterious Program : Principles of Imperative Computation (Spring 2018) Frank Pfenning

CSE 331 Software Design & Implementation

CS 3 Introduction to Software Engineering. 3: Exceptions

17. Assertions. Outline. Built-in tests. Built-in tests 3/29/11. Jelle Slowack, Bart Smets, Glenn Van Loon, Tom Verheyen

n Specifying what each method does q Specify it in a comment before method's header n Precondition q Caller obligation n Postcondition

17. Assertions. Jelle Slowack, Bart Smets, Glenn Van Loon, Tom Verheyen

Exceptions and assertions

CS 315 Software Design Homework 3 Preconditions, Postconditions, Invariants Due: Sept. 29, 11:30 PM

UC Santa Barbara. CS189A - Capstone. Christopher Kruegel Department of Computer Science UC Santa Barbara

Software Development. Modular Design and Algorithm Analysis

CSC Advanced Object Oriented Programming, Spring Specification

Assertions & Design-by-Contract using JML Erik Poll University of Nijmegen

Assertions and Exceptions Lecture 11 Fall 2005

Softwaretechnik. Lecture 08: Testing and Debugging Overview. Peter Thiemann SS University of Freiburg, Germany

Softwaretechnik. Lecture 08: Testing and Debugging Overview. Peter Thiemann SS University of Freiburg, Germany

Semantic Analysis. CSE 307 Principles of Programming Languages Stony Brook University

JAVA BASICS II. Example: FIFO

Lecture Notes: Hoare Logic

Announcements. Specifications. Outline. Specifications. HW1 is due Thursday at 1:59:59 pm

CS 161 Computer Security

Default arguments, documentation

OO Design Principles

Chapter 4 Defining Classes I

Programming with assertions Oracle guidelines

Repetition Through Recursion

Symbolic Execution and Proof of Properties

Arguing for program correctness and writing correct programs

High Quality Java Code: Contracts & Assertions

Lecture 3: Recursion; Structural Induction

Abstraction and Specification

Lecture 4: Procedure Specifications

Chapter 9. Exception Handling. Copyright 2016 Pearson Inc. All rights reserved.

Lecture 4 Specifications

Objectives for this class meeting. 1. Conduct review of core concepts concerning contracts and pre/post conditions

Design Patterns: State, Bridge, Visitor

Lecture Notes on Contracts

Designing Robust Classes

A Foundation for Programming

Reasoning About Imperative Programs. COS 441 Slides 10

Eiffel: Analysis, Design and Programming. ETH Zurich, September-December Exception handling

Preconditions and Postconditions

Lecture Notes on Memory Layout

Hoare Logic: Proving Programs Correct

Text Input and Conditionals

Design Principles: Part 2

Contracts. Dr. C. Constantinides. June 5, Department of Computer Science and Software Engineering Concordia University Montreal, Canada 1/71

Outline. Design Principles: Part 2. e.g. Rectangles and Squares. The Liskov Substitution Principle (LSP) ENGI 5895: Software Design.

Array Based Lists. Collections

Adding Contracts to C#

Functions. x y z. f (x, y, z) Take in input arguments (zero or more) Perform some computation - May have side-effects (such as drawing)

Lecture 3 Notes Arrays

The Contract Pattern. Design by contract

Software Testing Prof. Meenakshi D Souza Department of Computer Science and Engineering International Institute of Information Technology, Bangalore

Object-Oriented Design

Lecture Notes on Arrays

Type Hierarchy. Comp-303 : Programming Techniques Lecture 9. Alexandre Denault Computer Science McGill University Winter 2004

Verification Condition Generation

Design to interfaces. Favor composition over inheritance Find what varies and encapsulate it

CS11 Advanced Java. Winter Lecture 2

Lecture 10 Assertions & Exceptions

Lecture Outline. COOL operational semantics. Operational Semantics of Cool. Motivation. Lecture 13. Notation. The rules. Evaluation Rules So Far

A comparative study of Programming by Contract and Programming with Exceptions

Errors. And How to Handle Them

Representation Invariants and Abstraction Functions

Relaxed Memory-Consistency Models

Software Engineering Testing and Debugging Testing

Design by Contract: An Overview

Pages and 68 in [JN] conventions for using exceptions in Java. Chapter 8 in [EJ] guidelines for more effective use of exceptions.

CSE 331 Software Design and Implementation. Lecture 12 Assertions & Exceptions

Specifications. CSE 331 Spring 2010

Object-Oriented Design

Outline. software testing: search bugs black-box and white-box testing static and dynamic testing

Assoc. Prof. Marenglen Biba. (C) 2010 Pearson Education, Inc. All rights reserved.

CHAPTER 6 Design by Contract. Literature. When Design by Contract? Why Design By Contract?

6.170 Recitation #5: Subtypes and Inheritance

Outline. Introduction. 2 Proof of Correctness. 3 Final Notes. Precondition P 1 : Inputs include

Introduction to Programming in C Department of Computer Science and Engineering. Lecture No. #29 Arrays in C

CSE P 501 Exam 8/5/04

Lecture 9 / Tutorial 8 Software Contracts

Lecture 12 Assertions & Exceptions

Object Oriented Program Correctness with OOSimL

Dynamic Analysis Techniques Part 2

Type Checking in COOL (II) Lecture 10

Relaxed Memory-Consistency Models

Chapter 3. Set Theory. 3.1 What is a Set?

SPIM Procedure Calls

Transcription:

Readability [Skrien 4.0] Programs must be written for people to read, and only incidentally for machines to execute. Abelson & Sussman Use a good set of coding conventions, such as the ones given in the Google Java Style Guide. Pick a convention you deem worthy of note. Outline for Week 13 I. Readability II. Programming by contract A. Using assertions for correctness B. Class invariants C, Programming by contract Several good coding practices are covered in the Skrien text. Guideline: Give a variable the narrowest scope that you can. Give an example of this principle. Why is this a good principle? Guideline: Using standard idioms, make code as concise as possible. Example: In the following statement, b is a boolean variable: if (b == true) return true; else return false; This statement is far too verbose. An equivalent and much more readable statement is In most cases, this can be made even more readable. How? Guideline: Variable names should be neither too short nor too long. Consider a variable that controls whether a while-loop is exited. Week 13 Object-Oriented Languages and Systems 1

while (variable) { What is a good name for this variable? Which should be shorter, in general? Variable names or names of constants? In general, names that are used less frequently can be longer. Guideline: Names should be descriptive of the entity they apply to. They should not be vague or overly general. Give an example of a bad (variable, method, etc.) name you have encountered in code that you were refactoring or interfacing to. Here are some examples from Expertiza. Guideline: Names should not be redundant. Suppose course_controller.rb contains a method called create_course. What should it be? Suppose it contains a method called create_section. What should it be? Guideline: Factor out duplicated code. If a program has two places where the same sequence of instructions is being executed, it is almost always beneficial to move the duplicated code into a separate procedure. Example: Suppose you are developing a class of objects one of whose responsibilities is to parse an input string, such as a complicated mathematical expression. Part of the process of parsing involves checking that the input is valid. So the class might have a method like this: public void parse(string expression) { CSC/ECE 517 Lecture Notes 2016, Edward F. Gehringer 2

...do some parsing... if(! nexttoken.equals("+") ) { //error System.out.println ("Expected +, but found " + nexttoken); System.exit(1);...do some more parsing... if(! nexttoken.equals("*") ) { //error System.out.println ("Expected *, but found " + nexttoken); System.exit(1);... How can we clean this code up? private void handleerror(string message) { System.out.println(message); System.exit(1); public void parse(string expression) {...do some parsing... if(! nexttoken.equals("+") )...do some more parsing... if(! nexttoken.equals("*") )... Besides being more readable, this code has another advantage. What? Guideline: A method should do only one thing and do it well. Week 13 Object-Oriented Languages and Systems 3

Here's an example of a method to avoid: void dothisorthat(boolean flag) { if( flag ) {...twenty lines of code to do this... else {...twenty lines of code to do that... How should we change it? Using assertions for correctness How can we know that software is correct? It is only correct if it does what it is supposed to do. But how do we know what it is supposed to do? We need a specification. For example, is x = y + 5 a correct statement? You need to know what the statement is supposed to do. If the specification is, Make sure x and y have different values, then the statement is. But if the specification is, Make sure that x has a negative value, then the statement is. So, software correctness is a relative notion. CSC/ECE 517 Lecture Notes 2016, Edward F. Gehringer 4

Specifications are expressed through assertions. Not only do assertions help us determine whether the program is correct, they also help document the program, and provide a basis for systematic testing and debugging. A correctness formula is an expression {P S {Q It means that any execution of S, starting in a state where P holds, will terminate in a state where Q holds. In this formula, P is called the precondition, and Q is called the postcondition. This sounds simple, but the implications take some getting used to. Here is a trivial correctness formula, which holds as long as x is an integer: {x >= 9 x = x + 5 {x >= 13 It looks like this is a typo. After all, we could also strengthen the postcondition to read, {x >= 14 This postcondition is stronger than the original postcondition, because there are values of x which satisfy the original postcondition but do not satisfy it. Given the original precondition, this is the strongest postcondition we can give and still have the program be correct. Similarly, given the original postcondition, we can also weaken the precondition. What is the weakest precondition we can give involving x to have the program be correct? Week 13 Object-Oriented Languages and Systems 5

From a formula that holds, you can always get another one that holds by strengthening the or weakening the. It is also interesting to consider what the strongest possible precondition would be. It is possible to give a precondition strong enough that the program is correct regardless of what it does. What would such a precondition be? Similarly, we can make things easy for the program by weakening the postcondition as much as possible: Any precondition and program will satisfy this. Preconditions and postconditions can be introduced into programs by using assertions. Java has an assert statement (more on this later). Example: nth roots [Skrien 4.6] Consider this method, and its preconditions and postconditions: //Precondition: n 0 and (n is odd or value 0) //Postcondition: The n-th root of the double // value is returned. // If n is even, the positive n-th root // is returned. // If n is odd, the n-th root will have // the same sign as the value. public double nthroot(double value, int n) {... Whose responsibility is it to ensure that the preconditions are satisfied before calling the method? CSC/ECE 517 Lecture Notes 2016, Edward F. Gehringer 6

Suppose the preconditions are not satisfied. What can happen when the method is called? However, it is usually better if clients of the routine know what could happen in all cases. What can we do to make this happen? This leads to the following code: //Postcondition: The n-th root of the double // value is returned. // If n is even, the positive n-th root // is returned. // If n is odd, the n-th root will have // the same sign as the value. // If // public double nthroot(double value, int n) {... Why is this better? Is it always good to check whether the (original) preconditions are satisfied? It is a very good idea to write our code so that preconditions and postconditions can be checked. This is done with the Java assert statement. The assert statement has the form or assert expression1; assert expression1: expression2; The first form simply raises an AssertionError if the assertion is not true. The second form associates the value of expression2 with the AssertionError if an error is triggered. The value of expression2 should be something that will be useful in debugging. Week 13 Object-Oriented Languages and Systems 7

We could code the postcondition checks at the end of the nthroot method (assuming it returns result): assert Math.pow(result, (float) n) == value); if (n % 2 == 0) assert result > 0; else assert result * value > 0; Because checking of assertions may be quite expensive, it can be enabled or disabled at run time: To enable assertions at various granularities, use the -enableassertions, or -ea, switch. To disable assertions at various granularities, use the -disableassertions, or -da, switch. You specify the granularity with the arguments that you provide to the switch. See Enabling and Disabling Assertions. By default, assertions are disabled at run time. Consider again the Liskov Substitution Principle: Class S should be made a subclass of class C only if, for every method in C s and S s interface, S s method accepts as input all the values that C s method accepts (and possibly more) and does everything with those values that C s method does (and possibly more). How should we rephrase it in terms of preconditions and postconditions? Class S should be made a subclass of class C only if, for every method with identical signatures in C s and S s interface, the preconditions for C s method are no weaker than the for S s method, and the postconditions for C s method are no stronger than the for S s method. CSC/ECE 517 Lecture Notes 2016, Edward F. Gehringer 8

Class invariants [Skrien 4.5] Preconditions and postconditions tell us what happens while a method of class C is executing. Class invariants tell us what is true while a method of class C is not executing. Stated another way, preconditions and postconditions express properties of individual routines. We also need a way to express the global properties of instances of a class, properties that must be preserved by all routines. Such properties will make up the class invariant, capturing the integrity constraints characterizing a class. Consider the MyStack example from Week 10: public class MyStack {- private java.util.stack stack; public MyStack(){stack = new java.util.stack(); public void push(object o) { stack.push(o); public Object pop() { return stack.pop(); public object peek() { return stack.peek(); public boolean isempty(){return stack.empty(); It uses a java.util.stack(), which has capacity and size attributes. The attributes of the class Vector representation and integers capacity and size constitute the representation of a stack. Some properties cannot easily be expressed by preconditions and postconditions. An example is 0 <= size; size <= capacity Week 13 Object-Oriented Languages and Systems 9

A class invariant applies to every class instance, as a whole. This is different from preconditions and postconditions, which characterize individual routines. Programming by contract By associating pre- and postcondition assertions with a method m, the class tells its clients 1 If you promise to call m with pre satisfied then I, in return, promise to deliver a final state in which post is satisfied. As in human relationships, any good contract between classes entails obligations as well as benefits for both parties (the client and the supplier ). The precondition binds the. It defines the conditions under which a call to the routine is legitimate. It is an obligation for the. and a benefit for the The postcondition binds the. It defines the conditions that must be ensured by the routine on return. It is an obligation for the. and a benefit for the Let us take a look at one of the contracts we specified in the nth-root method. nth root Obligations Benefits Client (Satisfy precondition) (From postcond.) Supplier (Satisfy postcond.) (From precond.) 1 This discussion is taken from Bertrand Meyer s Object-Oriented Software Construction, 11,6, CSC/ECE 517 Lecture Notes 2016, Edward F. Gehringer 10

In case you haven t noticed it, one of the contract rules goes against conventional software-engineering wisdom. It is shocking to some, but is one of the method s main contributions to software reliability. Recall: If the precondition is not satisfied, the supplier doesn t have to do anything at all. It can go into an infinite loop, or even crash the system without violating the contract. This implies that when you are writing a routine, it s not your responsibility to check whether the preconditions are satisfied. For example, if a square-root function has the precondition x >= 0 you don t need to check whether the argument really is 0. Actually, it is not only useless, but actually harmful, to test whether the precondition is met. This is Meyer s non-redundancy principle: Under no circumstances shall the body of a routine ever test for the routine s precondition. This rule is the reverse of defensive programming advocated by many software-engineering textbooks. What is the rationale for this rule? Design by contract invites you to identify the consistency conditions that are necessary to the proper functioning of each client-supplier contract, and to specify, for each one of the conditions, whose responsibility it is to enforce it. Week 13 Object-Oriented Languages and Systems 11

Meyer calls this Zen and the art of software reliability: guaranteeing more by checking less. Who is the enforcer? OK, so the client and the supplier aren t both supposed to check that the condition is satisfied. Who should be the one to check it? One of the choices is tolerant, while the other is demanding : Choice 1 ( demanding ): The responsibility of checking is assigned to clients. Then where will the condition appear? Choice 2 ( tolerant ): The responsibility of checking is assigned to the supplier. Then where will the condition appear? Which one of these approaches is tolerant? Which approach is better, tolerant or demanding? Well, What is an advantage of the tolerant style? What is an advantage of the demanding style? A good routine author does not try to outsmart his clients. If he is not sure what to do in a specific case, he excludes it in the precondition. CSC/ECE 517 Lecture Notes 2016, Edward F. Gehringer 12