I have created a simple system to get hands on experience with OOPS design and some features in Java:
The system is:
- A
ClassOfStudents
contains Students - A
Student
contains a list of scores - A
Student
can be aPartTimeStudent
orFullTimeStudent
- A score is valid only if it is between 20 and 100
I have:
- Used enum for gender as it is a set of constants
- Created a user-defined exception to check for business rule
- Made student as abstract to make it extensible
- Used compare to reverse the natural order of sort and able to sort students
Queries
Please go through the code and feel free to advice all the OOPS design enhancements. I am new to OOPS and want to really understand.How to make code more extensible, reusable, secure. Some of the questions I have encountered while coding are:
- I don't want to create a object when score is not valid. I can achieve this by checking for score before using creating an object. But is there any other way?
- I am throwing an user defined exception and catching it immediately. Is it good practice? I don't want to interrupt the flow and continue.
- I am using logging for the first time. Is it the good way to log?
- I tired to implement as many as OOPS concepts but am unable to think of an interface. Please suggest a good use case to use an interface.
- How can I improve the exception handling (robustness)? Is there any other way I can add the student to
studentList
in theClassOfStudents
whenever a new student is created? - Also suggest some new feature I can add to learn more OOPS/Java concepts.
I have poster another question similar and got great response. I haven't implemented some of the feature like return immutable lists, not use throws for main here but grasped the concepts.
import java.util.*;
import java.util.logging.*;
//I am trying to write extensible calss. So I have declared Student as abstact.
//FullTimeStudent and PartTimeStudent sub classes
//Moreover a Student need to be a FullTime are PartTime so Student object cannot be created.
//I am using protected to scoreList. It is a good way?
class ClassOfStudents
{
private List<Student> studentList = new ArrayList<Student>();
public void addStudent(Student student)
{
studentList.add(student);
}
public List<Student> getStudentList()
{
return studentList;
}
}
abstract class Student implements Comparable<Student>
{
private String name;
private Address address;
private Gender gender;
protected List<Score> scoreList = new ArrayList<Score>(); //Because the subclass need to access
Student(String name)
{
this.name = name;
this.gender = Gender.UNKNOWN;
}
Student(String name, Gender gender)
{
this.name = name;
this.gender = gender;
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public String toString()
{
return name+" "+gender;
}
public void addScore(Score score)
{
scoreList.add(score);
}
public List<Score> getScores()
{
return scoreList;
}
// Reverse of natural order of String.
public int compareTo(Student otherStudent)
{
return -1 * this.name.compareTo(otherStudent.getName());
}
public abstract boolean checkScores();
}
//Inheritance
class FullTimeStudent extends Student
{
FullTimeStudent(String name)
{
super(name);
}
FullTimeStudent(String name, Gender gender)
{
super( name, gender);
}
public boolean checkScores()
{
for(Score score : scoreList)
{
if (score.getStatus() == false)
return false;
}
return true;
}
}
//Inheritance
class PartTimeStudent extends Student
{
PartTimeStudent(String name)
{
super(name);
}
PartTimeStudent(String name, Gender gender)
{
super( name, gender);
}
public boolean checkScores()
{
int countScoreFail = 0;
for(Score score : scoreList)
{
if (score.getStatus() == false)
countScoreFail++;
}
System.out.println(countScoreFail);
if (countScoreFail >= 3)
return false;
else
return true;
}
}
class Address
{
private String streetAdress1;
private String phoneNumber;
private String zipCode;
//Constructor, Setters and getters of Address
}
enum Gender
{
MALE,FEMALE,OTHER,UNKNOWN;
}
// Score can be between 20 to 100.
//Score can only be incrmented / decremented by 1.
//If Score < 40 , then status is false. Else true
//I dont want to create a object when score is not valid. I can do this by checking for score before using new. But is there any other way?
//I am throwing an user defined exception and catching it immediately, is it a good practice. I dont want to disturb the flow and continue?
//I am using logging for the first time. Is it the good way to write this?
class Score
{
private int score;
private boolean status = false;
Score(int score) throws scoreException
{
setScore(score);
}
public void setScore(int score) throws scoreException
{
if(score < 20 || score > 100)
{
try{
System.out.println("Invalid Score!!!");
throw new scoreException();
}
catch(scoreException e)
{
Logger logger = Logger.getLogger("myLogger");
logger.log( Level.FINE,"Hello logging");
}
}
else
{
this.score = score;
if(score >= 40)
status = true;
}
}
public int getScore()
{
return score;
}
public boolean getStatus()
{
return status;
}
public String toString()
{
return score+" "+status;
}
}
class scoreException extends Exception
{
public String toString()
{
return "Entered Marks are not valid";
}
}
public class Test{
public static void main(String []args)throws scoreException
{
//Polymorphism
ClassOfStudents c1 = new ClassOfStudents();
Student s1 = new FullTimeStudent("John");
Student s2 = new PartTimeStudent("Nancy",Gender.FEMALE);
c1.addStudent(s1);
c1.addStudent(s2);
List<Student> studentList = c1.getStudentList();
Collections.sort(studentList);
for(Student student : studentList)
{
System.out.println(student);
}
//*************************
s1.addScore(new Score(10));
s1.addScore(new Score(50));
s1.addScore(new Score(30));
System.out.println("Student is "+s1);
//Even for invalid score objects are created. I dont want them to be created.
System.out.println("Printing content of all the scores of student");
for(Score score : s1.getScores())
{
System.out.println(score);
}
System.out.println("Are all scores greater than 40?? ::"+s1.checkScores());
//****************************
System.out.println("Student is "+s2);
s2.addScore(new Score(10));
s2.addScore(new Score(50));
s2.addScore(new Score(30));
//Even for invalid score objects are created. I dont want them to be created.
System.out.println("Printing content of all the scores of student");
for(Score score : s2.getScores())
{
System.out.println(score);
}
System.out.println("Are all scores greater than 40?? ::"+s2.checkScores());
}
}
toString
method would print something likeMartin Male
. Why would my gender be important in the string representation of myStudent
object? \$\endgroup\$enum
. And kudos for havingGender.UNKNOWN
for a default value. However if javaenum
defaults to zero, then putUNKNOWN
at the front of the list. \$\endgroup\$