Java 2

Week 1

 

Software Development Life Cycle, Steps 1-3

Fraction Class

Software Development Life Cycle (SDLC)

1. Planning

  • The planning phase is where you define the project's goal at a high level.
  • Answer the question "What are we building?"

Project Goal: To create a command-line application that performs basic arithmetic on fractions.

Project Scope

  • Project scope defines the boundaries of a project, such as what is included and excluded, thereby preventing scope creep and promoting efficient project execution. 

  • Answer the question "What is the scope of the project?"

In Scope: The calculator must handle addition, subtraction, multiplication, and division. It must accept valid whole numbers, improper fractions, and mixed numbers (e.g., 3, 5/3, 1 2/3). All results must be simplified and displayed as both an improper fraction (e.g., 5/3) and a mixed number (e.g., ​1 2/3).

Out of Scope: A graphical user interface (GUI) or handling square roots are not part of this initial project.

Feasibility Analysis

  • A feasibility analysis is a comprehensive evaluation of a proposed project to determine its viability. It assesses various factors like technical, financial/economic, operational, legal, and market aspects to determine if the project is likely to succeed and if it's worth pursuing. 

  • Answer the question, "Is it feasible?"

Technical: Yes, it is possible, as Java has all the necessary tools to handle the arithmetic and user input.

Economic: The primary resources needed are a developer proficient in Java and a computer with a Java Development Kit (JDK). The cost is primarily the developer's time (approximately 8-10 hours). No special software or hardware is needed.

Operational: Once built, this project can be included as part of a suite of mathematical calculators. It will serve its purpose without disrupting any existing workflows.

2. Analysis

  • The analysis phase focuses on gathering detailed requirements from stakeholders (e.g., the user or project owner).
  • The goal is to understand exactly what the system must do.
  • These are broken down into functional and non-functional requirements.

Functional Requirements

  • Functional Requirements: (define what the program does)

    1. The system must allow a user to input two fractions and an arithmetic operator (+, -, *, /).

    2. The system must correctly parse various input formats: a/b (e.g., 2/3), a b/c (e.g., 1 1/2), and a (e.g., 4).

    3. The system must perform the specified arithmetic operation. For example: 2/3+11/2 should equal 21/6.

    4. The system must handle and report errors, such as division by zero or invalid input (e.g., "hello").

    5. The final result must always be simplified to its lowest terms. For example, a raw result of 10/6 must be simplified to 5/3.

    6. The final result must be displayed in two formats: as an improper fraction (e.g., 5/3) and as a mixed number (e.g., 1 2/3).

Non-Functional Requirements

  • Non-Functional Requirements: (defines how it will be done)

    1. The application must be written in the Java programming language.

    2. It must run as a console (command-line) application.

    3. Calculations must be accurate and computationally efficient.

Software Requirements Specifications (SRS)

  • In larger project, this phase produces a Software Requirements Specification (SRS) document, which details everything the final product needs to be and do.

  • More information:

3. Design

  • The design phase is where you create the blueprint for the system based on the requirements gathered in the analysis phase.
  • This includes defining the system's architecture, data structures, and algorithms.
  • This is where tools like UML diagrams and flowcharts are essential.

Model-View-Controller

  • MVC architecture is a widely used software design pattern that separates an application into three interconnected packages, making applications more organized, easier to maintain, and testable.
    • The Model manages the application's data and business logic
    • The View handles the user interface and presentation
    • The Controller acts as the intermediary, receiving user input, interacting with the Model, and selecting the appropriate View to display to the user.
  • The Laravel PHP framework does a great job of organizing web projects.
  • Jakarta EE requires manual organization

Classes

  • In object-oriented programming, classes create the blueprint for objects in the system.
  • We'll structure this application into two classes:

    • A Fraction class: This will be the core (the model) of our application. It will hold the data for a single fraction (numerator and denominator) and contain the logic for performing arithmetic operations, simplification, and formatting.

    • A Calculator (or Main) class: This will handle getting input from the console (the view) and orchestrate the operations (the controller) by creating Fraction objects and calling their methods.

What is UML?

  • Class diagrams show the classes of the system, their relationships, and the attributes and operations (methods).

  • Classes form the main building blocks of an object-oriented application.

Person
- String firstName
+ getFirstName() : String
+ setFirstName(String firstName) : void
+ toString() : String

Class Diagrams

Three Boxes

  • Classes are depicted as boxes with three sections:
    • The top box indicates the name of the class. The name is typically a singular noun. Write class names in UpperCamelCase.
    • The middle box lists the attributes of the class (the information stored about an object)
    • The bottom box lists the methods (the operations an object or class do).
ClassName
- attributes
+ methods

Access Modifiers

  • The + symbol represents a public access modifier, meaning all other classes have access.
  • The - symbol represents a private access modifier, meaning only the current class has access.
  • The / symbol (not shown) represents a derived modifier - a value not stored but is calculated from other attributes when needed
    • ​For example, GPA could be derived from a list of grades
  • The # symbol (not shown) represents a protected access modifier, meaning other classes in the same package has access to the attribute.
Person
- String firstName
+ getFirstName() : String
+ setFirstName(String firstName) : void
+ toString() : String

Data Types, Parameters, and Return Types

  • Method parameters are shown inside parentheses.
    • ​Getter methods and the toString method have no parameters.
    • Setter method parameters will typically match the attribute data type.
  • Method return types are shown after the colon.
    • Getter methods will always return the attribute data type.
    • Setter methods will always return void.
    • The toString method will always return a String.
Person
- String firstName
+ getFirstName() : String
+ setFirstName(String firstName) : void
+ toString() : String

Fraction Class Diagram

Fraction
- int numerator
- int denominator
+ Fraction()
+ Fraction(int numerator, int denominator)
+ getNumerator() :: int
+ setNumerator(int numerator) :: void
+ getDenominator() :: int
+ setDenominator(int denominator) :: void
+ toString() :: String
+ compareTo(Fraction other) :: int
- gcd(int a, int b) :: int
- lcm(int a, int b) :: int
+ simplify() :: void
+ toMixedNumber() :: String
+ add(Fraction other) :: Fraction
+ subtract(Fraction other) :: Fraction
+ multiply(Fraction other) :: Fraction
+ divide(Fraction other) :: Fraction
  • The numerator is the top number of the fraction
  • The denominator is the bottom number of
    the fraction
  • Attributes should typically have private access
  • Write non-constant attribute names in lowerCamelCase.
  • There is a default and parameterized constructor
  • Methods most often have public access.
    Write method names in lowerCamelCase.
  • The value(s) inside the parenthesis are the input parameter(s) and their data types.
    Write parameters in lowerCamelCase.
  • The values after the parenthesis are the return types.
  • The first methods are the constructors. The next set of methods are the getters and setters. Always include a toString method.

Class Diagrams

  • From the previous slide:
    • toString() will return a string like "5/3"
    • compareTo() can be used to sort a List of Fraction objects
    • gcd() is a private helper method to get the greatest common denominator of two integers
    • lcm() is a private helper method to get the least common multiple of two integers
    • simplify() is a private helper method to reduce the fraction
    • toMixedNumberString() will return a string like "1 2/3"

Mermaid Syntax

Mermaid Class Diagram

  • Here is an example of a single class with no related classes.
classDiagram
    class Fraction {
        - int numerator
        - int denominator
        + Fraction()
        + Fraction(int numerator, int denominator)
        + getNumerator(): int
        + setNumerator(int numerator): void
        + getDenominator(): int
        + setDenominator(int denominator): void
        + toString() : String
        + compareTo(Fraction other) : int
        - simplify() : void
        - gcd(int a, int b): int
        + toMixedNumberString() : String
        + add(Fraction other) : Fraction
        + subtract(Fraction other) : Fraction
        + multiply(Fraction other) : Fraction
        + divide(Fraction other) : Fraction
    }

Mermaid Flowchart

  • Here are two examples of top-down flowcharts. Note how both examples are different, but they result in the same output
    • Circles are used to indicate the start and end
    • A parallelogram is used to indicate input
    • A diamond is used for decision making
    • Rectangles are used for process steps
flowchart TD
    A@{ shape: circle, label: "Start" } --> B@{ shape: lean-r, label: "Input Fraction 1 (n1/d1)<br>Input Fraction 2 (n2/d2)" };
    B --> C@{ shape: diamond, label: "Are<br>d1 and d2<br>the same?" }
    C -- Yes --> D
    C -- No --> E@{ shape: rect, label: "Find the Least Common Multiple (LCM) of d1 and d2" };
    E --> F@{ shape: rect, label: "Use the LCM to convert both fractions with the same denominator" };
    F --> D@{ shape: rect, label: "Add numerators n1 and n2. Keep denominator the same." };
    D --> G@{ shape: rect, label: "Display result as a simplified mixed number" };
    G --> H@{ shape: circle, label: "End" };
flowchart TD
    A@{ shape: circle, label: "Start" } --> B@{ shape: lean-r, label: "Input Fraction 1 (n1/d1)<br>Input Fraction 2 (n2/d2)" };
    B --> C@{ shape: rect, label: "Set new numerator by cross multiplying<br>(n1 * d2 + d1 * n2)" };
    C --> D@{ shape: rect, label: "Set new denominator<br>(d1 * d2)" };
    D --> E@{ shape: rect, label: "Display result as a simplified mixed number" };
    E --> F@{ shape: circle, label: "End" };

In-Class Group Activity

  • In groups of 2 to 3 students, create a flowchart for two of the other method operations.
    • simplify -> Convert 48/27 to 16/9, Convert 1/-2 to -1/2
    • toMixedNumberString() -> Convert 16/9 to 1 7/9, Convert 2/1 to 2, Convert 0/2 to 0
    • subtract(Fraction other) :: Fraction
    • multiply(Fraction other) :: Fraction
    • divide(Fraction other) :: Fraction

Java 2 - Week 1

By Marc Hauschildt

Java 2 - Week 1

  • 94