200 likes | 293 Views
JML Specifications for StressFree classes. Class design method identification Method specification in JML preconditions postconditions Class invariant specification in JML. More JML Language. non-null - designates that a variable cannot be null for any object in this class.
E N D
JML Specifications for StressFree classes • Class design • method identification • Method specification in JML • preconditions • postconditions • Class invariant specification in JML
More JML Language non-null - designates that a variable cannot be null for any object in this class. spec_public - required for private instance variables that are mentioned in JML method specifications (since methods themselves are public, so are their specs). pure - designates a method that has no local side effects (assignments to class variables) and no infinite loops assignable \nothing ; - designates that no variables can be assigned by the method (similar to pure). assignable v ; - designates that only variable v can be assigned by a method (default = assignable \everything ; )
Identifying methods Use cases suggest new methods in various classes. E.g., enrollInCourses suggests: In class System: getStatus (open or closed) In class CourseOffering: isFull addStudent In class Schedule: addCourse viewCourseOfferings
Writing method specifications: E.g., TimeSlots private /*@spec_public @*/ String days; // MTWHFSU = Mon, Tue, Wed, Thu, Fri, Sat, Sun // TBA = undefined private /*@spec_public @*/ String startTime; // Military time. E.g. 13:30 means 1:30pm private /*@spec_public @*/ String endTime; // true if neither this nor other is TBA, // this.days and other.days has a day in common, and // this and other have a time overlap. public boolean conflictsWith (TimeSlot other) // true if other.startTime precedes this.endTime public boolean timeOverlap (TimeSlot other) JML specs needed here
Specifying the conflictsWith method /*@ ensures \result == !days.equals("TBA") && !other.days.equals("TBA") && (\exists int i; 0 <= i && i < days.length(); (\exists int j; 0 <= j && j < other.days.length(); days.charAt(i) == other.days.charAt(j))) && this.timeOverlap(other); @*/ public /*@ pure @*/ boolean conflictsWith (TimeSlot other) { This means “No local side effects.” Also,days, startTime, endTime must be declared spec-public.
Specifying prerequisite satisfaction A Transcript satisfies all of a Course’s prerequisites if it has at least one CourseRecord whose id is in the set defined by each prerequisite. E.g., suppose the Course c = CSCI210 has prerequisites “both CSCI107 and either one of MATH200 or CSCI189”. This shows as the Java Vector of regular expressions: [CSCI107, MATH200|CSCI189] The Transcript t can satisfy this by containing a CourseRecord that matches each regular expression. JML specifications for the method t.meetsPrerequisites(c) should be added to the Transcript class before the code is written.
What would the JML specifications look like? • In the Transcript class: • public HashMap myRecords = new HashMap(); • /*@ • requires course != null • ensures result == (\forall Regexp p; p == course.getPrerequisites().next(); • (\exists CourseRecord r; r == myRecords.next(); • p.match (r.id)); • @*/ • publicboolean meetsPrerequisites(Course course) { • // your code here • returnfalse; • } • Note: In this case, the specs may be easier to write than the code (these quantifiers suggest loops).
JML class invariant A class invariant defines all the valid states (values of the instance variables) of any object in the class. E.g. Consider the class Student, with instance variables id, name, and year. An invariant could embody the following ideas: id = an integer in the range 1..1620. name = a nonempty string. year = a valid graduation year (e.g., 2006). In JML, this can be written: /*@ invariant id.intValue() > 0 && id.intValue() <=1620 && name != null && name.length() > 0 && (\exists int i; 2006 <= i && i <= 2009; i == year) @*/ Notes: A specification can be: 1) too lenient (some instance variables can be null), or 2) too strict (what about next year’s students?)
Specifying Java collections A collection in Java can be any of several classes E.g., TreeSet, Vector, HashMap, ArrayList, etc. Picking the best collection for an implementation includes the following: 1. Unique keys: Some collections have the feature that each member’s key is distinct. E.g., Hashtable. 2. Ordering: A collection may require that its members be sorted, in which case they must be Comparable. E.g., Students 3. Traversal: An Iterator allows visiting the members of a collection, one at a time. E.g., the TreeSet that contains the keys for CourseOfferings can be traversed using an Iterator. Note: All these choices and operators can be used in JML specifications.
HashMaps and their keys Class Element KeyUsage (in JML specs) Students Student (s) id s.getId() Courses Course (c) id c.getId() CourseOfferings CourseOffering (co) getCourse().id+section+labsection co.getKey() Transcripts Transcript (t) student.id t.getId() TimeSlots TimeSlot (tm) id tm.getId() CourseRecords CourseRecord (cr) student.id+courseOffering.getKey() cr.getKey() Instructors Instructor (in) name in.getName()
Student vs. Students • Students can be a HashMap whose keys are Student.id’s. • To retrieve a Student s from Students ss, say ss.get(s.getId()); • If ss has no entry whose key is id, null is returned. • To see if an individual Student s appears in Students ss, say • ss.containsKey(s.getId()); • If ss has no entry with key == id, false is returned. • To traverse the set of keys of a HashMap, use: • ss.keySet() and contains. • When writing JML specs, assume all Java classes (e.g., HashMap, • String) are correct. So their methods can appear in the specs.
Students vs. StudentDB: the SQL interface Students is a HashMap. Its keys are Student.id’s. It is not persistent. That is, it forgets all updates from past runs. StudentDB is an SQL Table. Its keys are Student.id’s. It is persistent. That is, it remembers updates from past runs. To retrieve an individual Student s from StudentDB table sdb, we can define a method sdb.get(s.getId()); If this fails, null is returned. To see if an individual Student s appears in StudentDB sdb, we can define a method sdb.containsKey(s.getId()); If sdb has no entry with key id, false is returned. To add or replace Student s in the StudentDB table sdb, we can define a method sdb.put(s).
A Sketch of some important SQL Commands Statement stmt; ResultSet rs; Retrieval – get Student s out of the StudentDB table rs = stmt.executeQuery(“select * from StudentDB where ” + “id = ” + s.getId()); If rs != null then the query was successful, so you can retrieve all the instance variables for that student: s.setName(rs.getString(“name”)); s.setYear(rs.getInt(“year”)); Query – The above can also be used to query a Table, by testing if rs == null. Update – insert new values for Student s into a row of the StudentDB table. stmt.executeUpdate(“insert into StudentDB(id, name, year) values( “ + + s.getId() + “,” + s.getName() + “,” + s.getYear() + “)”);
The Student class invariant publicclass Student { privateint id; private String name; private String year; public Instructor advisor; public Schedule schedule; public Transcript transcript; /*@ id > 0 && id <=1620 && name != null && name.length() > 0 && (\exists int i; 2006 <= i && i <= 2009; i == year) && transcript != null && (schedule == null || (\forall CourseRecord cr; schedule.getMyClasses().keySet().contains(cr); cr.getSchedule().getStudent().getId().equals(id))) @*/
Debugging conflictsWith If this method is buggy, can our JML specs help find the error? publicboolean conflictsWith (TimeSlot other) { if (this.days.equals("TBA") || other.days.equals("TBA")) returnfalse; for (int i=0; i<other.days.length(); i++) if (other.days.indexOf(this.days.substring(i, i)) >= 0) if (this.timeOverlap(other)) returntrue; // day in common and time ovelap elsereturnfalse; // day in common, no time overlap returnfalse; // no day in common }
Recall Design by Contract The relation between a class (method) and its client (caller) is a formal agreement
Finding the contracts in StressFree Each use case has at least one contract • Who is the client? • Who is the supplier? • What are the client’s obligations? • What are the supplier’s obligations? (The benefits are usually implicit) Example: the viewOfferings use case • Client = Student, Registrar, or Instructor class • Supplier = CourseOfferings class • Client obligations: to provide a valid set of course ids. • Supplier obligations: to display the id, title, time slot, prerequisites, distribution, capacity, and enrollment for all courses in the set.