Search code examples
oopdesign-by-contractpreconditions

Should precondition methods be public or private?


The precondition code in methods markStudent(...) and getUnitMark(...) makes use of other method of the class: isEnrolled(...) and hasCompletedAssessments(...).

import java.util.ArrayList; 
import java.util.HashMap;
public class Unit {
    private String code;
    private String name;
    private HashMap<Integer, Student> enrolledStudents = new HashMap<Integer, Student>(); 
    private AssessmentScheme assessmentScheme = null;
    private HashMap<Assessment, HashMap<Student, Mark> > Marks

    public Unit(String newCode, String newName) { code = newCode;
             name = newName;
       }
    public void enrolStudent(Student newStudent) {
             enrolledStudents.put(newStudent.getPersonID(), newStudent);
       }
    public void unenrolStudent(Student student) {
             enrolledStudents.remove(student.getPersonID());
       }

    public boolean isEnrolled(Student student) {
            return enrolledStudents.containsKey(student.getPersonID()); }
    public ArrayList<Student> getEnrolledStudents() {
            ArrayList<Student> students = new ArrayList<Student (enrolledStudents.values());
            return students; }

    public boolean hasCompletedAssessments(Student student) { boolean hasCompleted = true;
            for (Assessment a : assessmentScheme.getAssessments()) {       hasCompleted &= Marks.get(a).containsKey(student);
} 
    return hasCompleted; }

    public void markStudent(Assessment assessment, Student student, int score, String comment) throws Exception {
        /* Start Preconditions */
        // Precondition: studentEnrolledInUnit
        if (! isEnrolled(student)) {
             } throw new Exception("Precondition violated: studentEnrolledInUnit");
        // Precondition: scoreInValidRange
        if ((score < 0 || (score > assessment.getWeight()) } 
            throw new Exception("Precondition violated: scoreInValidRange"); /* End Preconditions */
        Mark mark = new Mark(assessment, student, score, comment);
               Marks.get(assessment).put(student, mark);
}

The question is, should methods used in precondition code, such as isEnrolled(...)and hasCompletedAssessments(...), be public or private?

From my understanding of design by contract, the client should check if its arguments obey the precondition. This means that the methods used in precondition code should be public for the client classes to do the checking. However in the markStudent method, it's clearly seen that the method is checking for its own precondition. Can someone help?


Solution

  • There is no harm to making these methods public. That enables a client to ensure that their calls are legal. Clients don't have to do this if they know that their call is legal.

    It is perfectly fine for the method implementation to do its own checking as well, by calling a public method.