Skip to content
april-e1 edited this page Nov 19, 2024 · 2 revisions

Design Patterns Used

Composite Pattern

The Composite Pattern is a structural design pattern that allows clients to treat individual objects (leaves) and compositions of objects (composites), that is, clients can deal with single objects or groups of objects interchangeably. In the project, TestResultComposite and TestResultLeaf implement TestResultComponent. However, TestResultLeaf throws new UnsupportedOperationException for add() and remove() methods because a leaf cannot have children. The benefits of using this pattern include:

  • Scalability and Flexibility: objects in the hierarchy can be added or removed without affecting client code.
  • Readability: complexity of hierarchical operations (eg. printing) is reduced through the use of recursive methods.
  • Links: TestResultComponent, TestResultComposite, TestResultLeaf

Strategy pattern

The Strategy pattern is a behavioural design pattern that defines a family of algorithms, encapsulates each one, and makes them interchangeable. In the project, EvaluatingStrategy is the interface which defines common behaviour of all grading strategies. It declares the evaluate() method which is used by GradingContext to execute a concrete strategy. The concrete strategies (AttributeType, MethodBehaviour, MethodSignature and Main) each encapsulate different algorithms for evaluating tests. The StudentFolderProcessor works with GradingContext to determine which evaluation strategy to execute. The benefits of using this pattern include:

  • Flexibility: adding new grading strategies requires creating a new class that implements the EvaluationStrategy interface without affecting existing code.
  • Reusability: shared code functionality is reused across different strategies, reducing the risk of introducing bugs during modification.
  • Testability: strategies can be tested independently which improves the quality of code.
  • Links: EvaluationStrategy, [AttributeType, MethodBehaviour, MethodSignature, Main (Concrete Strategies)], GradingContext, StudentFolderProcessor

Template Pattern

The Template Pattern is a behavioural design pattern that defines the skeleton of an algorithm in the superclass but allows subclasses to override specific steps without changing the overall structure. In this project, JavaFileProcessor is a concrete implementation of FileProcessorTemplate which extracts, compiles and stores results for java files. The benefits of using this pattern include:

  • Extensibility: FileProcessorTemplate can be extended to create specialized file processors by overriding the abstract methods.
  • Consistency: The template method (processFile) employs a standardized workflow, ensuring consistency of layouts.
  • Links: FileProcessorTemplate, JavaFileProcessor

Conformance to SOLID

The Automated Judge System Group 8 has designed conforms to the SOLID Principles in the following ways:

Single Responsibility Principle (SRP)

The SRP states that a class should have only one responsibility, that is, only one reason to change. The Automated Judge System conforms to this principle by ensuring that each class performs one task. For example, PDFGenerator is responsible for only generating the PDF.

Open/Closed Principle (OCP)

The OCP states that classes should be open for extension but closed for modification. The system conforms to OCP by implementing interfaces that can be extended such as the EvaluationStrategy interface, which allows for different algorithms of evaluating tests.

Liskov Substitution Principle (LSP)

The LSP states that objects of subclasses must be substitutable with objects of its superclass without any unexpected behaviour. By using Composite Strategy, the LSP is adhered to as composite (TestResultComposite) and leaf (TestResultLeaf) objects can be used interchangeably without breaking the application.

Interface Segregation Principle (ISP)

The ISP states that classes must not be forced to implement code it does not use. This system conforms to ISP by modularizing the interfaces, allowing classes to implement only what is needed. For example, JavaFileProcessor implements only the required methods from FileProcessorTemplate.

Dependency Inversion Principle (DIP)

The DIP states that low level modules should not depend on high level modules. Rather, they should both depend on abstractions. Furthermore, abstractions should not depend on details, but details should depend on abstractions. In this system for example, high level modules such as GradingContext do not directly depend on specific strategies, thus adhering to this principle.

Class Diagram

class drawio