CS2103/T Jan '19
  • Week 1 [Jan 14]
  • Week 2 [Jan 21]
  • Week 3 [Jan 28]
  • Week 4 [Feb 4]
  • Week 5 [Feb 11]
  • Week 6 [Feb 18]
  • Week 7 [Mar 4]
  • Week 8 [Mar 11]
  • Week 9 [Mar 18]
  • Week 10 [Mar 25]
  • Week 11 [Apr 1]
  • Week 12 [Apr 8]
  • Week 13 [Apr 15]
  • Textbook
  • Admin Info
  • Report Bugs
  • Slack
  • Forum
  • Project Info
  • Instructors
  • Announcements
  • File Submissions
  • Tutorial Schedule
  • Team IDs
  • Java Coding Standard
  • samplerepo-things
  • Addressbook-level1
  • Addressbook-level2
  • Addressbook-level3
  • Addressbook-level4
  • Projects List
  • config.json templates for Reposense
  • Project Code Dashboard (BETA)
  • Previous WeekNext Week

    Week 4 [Feb 4]

    There are no tutorials this week due to CNY.

    • Get started on the project (i.e., defining your project direction and requirements). Try to do at least step 1 of mid-v1.0 project milestone before coming to the tutorial this week, and try to finish the remainder by the end of this week.

    • A heads up: next week is going to be HEAVY 😨 as it has two graded tasks -- both require significant team efforts and a substantial time period to complete. We urge you all to make full use of this week to prepare yourself for that challenge. In particular,

      • Try to reach mid-v1.0 fully i.e., complete all 3 steps.
      • If you are not familiar with Git and GitHub, review and complete the exercises from previous current week.
    • One part of this week's lecture is not covered in the textbook and is relevant for your project work for the upcoming project milestone v1.0. You are encouraged to attend this week's lecture even if you don't normally come to lectures.


    [W4.1] Requirements analysis

    [W4.1a] Requirements → Requirements → Introduction

    Can explain requirements

    A software requirement specifies a need to be fulfilled by the software product.

    A software project may be,

    • a brown-field project i.e., develop a product to replace/update an existing software product
    • a green-field project i.e., develop a totally new system with no precedent

    In either case, requirements need to be gathered, analyzed, specified, and managed.

    Requirements come from stakeholders.

    Stakeholder: A party that is potentially affected by the software project. e.g. users, sponsors, developers, interest groups, government agencies, etc.

    Identifying requirements is often not easy. For example, stakeholders may not be aware of their precise needs, may not know how to communicate their requirements correctly, may not be willing to spend effort in identifying requirements, etc.

    [W4.1b] Requirements → Requirements → Non-Functional Requirements

    Can explain non-functional requirements

    There are two kinds of requirements:

    1. Functional requirements specify what the system should do.
    2. Non-functional requirements specify the constraints under which system is developed and operated.

    Some examples of non-functional requirement categories:

    • Data requirements e.g. size, volatility, persistency etc.,
    • Environment requirements e.g. technical environment in which system would operate or need to be compatible with.
    • Accessibility, Capacity, Compliance with regulations, Documentation, Disaster recovery, Efficiency, Extensibility, Fault tolerance, Interoperability, Maintainability, Privacy, Portability, Quality, Reliability, Response time, Robustness, Scalability, Security, Stability, Testability, and more ...
    • Business/domain rules: e.g. the size of the minefield cannot be smaller than five.
    • Constraints: e.g. the system should be backward compatible with data produced by earlier versions of the system; system testers are available only during the last month of the project; the total project cost should not exceed $1.5 million.
    • Technical requirements: e.g. the system should work on both 32-bit and 64-bit environments.
    • Performance requirements: e.g. the system should respond within two seconds.
    • Quality requirements: e.g. the system should be usable by a novice who has never carried out an online purchase.
    • Process requirements: e.g. the project is expected to adhere to a schedule that delivers a feature set every one month.
    • Notes about project scope: e.g. the product is not required to handle the printing of reports.
    • Any other noteworthy points: e.g. the game should not use images deemed offensive to those injured in real mine clearing activities.

    We may have to spend an extra effort in digging NFRs out as early as possible because,

    1. NFRs are easier to miss  e.g., stakeholders tend to think of functional requirements first
    2. sometimes NFRs are critical to the success of the software.  E.g. A web application that is too slow or that has low security is unlikely to succeed even if it has all the right functionality.

    Given below are some requirements of TEAMMATES (an online peer evaluation system for education). Which one of these are non-functional requirements?

    • a. The response to any use action should become visible within 5 seconds.
    • b. The application admin should be able to view a log of user activities.
    • c. The source code should be open source.
    • d. A course should be able to have up to 2000 students.
    • e. As a student user, I can view details of my team members so that I can know who they are.
    • f. The user interface should be intuitive enough for users who are not IT-savvy.
    • g. The product is offered as a free online service.

    (a)(c)(d)(f)(g)

    Explanation: (b) are (e) are functions available for a specific user types. Therefore, they are functional requirements. (a), (c), (d), (f) and (g) are either constraints on functionality or constraints on how the project is done, both of which are considered non-functional requirements.

    [W4.1c] Requirements → Requirements → Prioritizing Requirements

    Can explain prioritizing requirements

    Requirements can be prioritized based the importance and urgency, while keeping in mind the constraints of schedule, budget, staff resources, quality goals, and other constraints.

    A common approach is to group requirements into priority categories. Note that all such scales are subjective, and stakeholders define the meaning of each level in the scale for the project at hand.

    An example scheme for categorizing requirements:

    • Essential: The product must have this requirement fulfilled or else it does not get user acceptance
    • Typical: Most similar systems have this feature although the product can survive without it.
    • Novel: New features that could differentiate this product from the rest.

    Other schemes:

    • High, Medium, Low
    • Must-have, Nice-to-have, Unlikely-to-have
    • Level 0, Level 1, Level 2, ...

    Some requirements can be discarded if they are considered ‘out of scope ’.

    The requirement given below is for a Calendar application. Stakeholder of the software (e.g. product designers) might decide the following requirement is not in the scope of the software.

    The software records the actual time taken by each task and show the difference between the actual and scheduled time for the task.

    [W4.1d] Requirements → Requirements → Quality of Requirements

    Can explain quality of requirements

    Here are some characteristics of well-defined requirements [📖 zielczynski]:

    • Unambiguous
    • Testable (verifiable)
    • Clear (concise, terse, simple, precise)
    • Correct
    • Understandable
    • Feasible (realistic, possible)
    • Independent
    • Atomic
    • Necessary
    • Implementation-free (i.e. abstract)

    Besides these criteria for individual requirements, the set of requirements as a whole should be

    • Consistent
    • Non-redundant
    • Complete

    Peter Zielczynski, Requirements Management Using IBM Rational RequisitePro, IBM Press, 2008


    Gathering Requirements

    [W4.1e] Requirements → Gathering Requirements → Brainstorming

    Can explain brainstorming

    Brainstorming: A group activity designed to generate a large number of diverse and creative ideas for the solution of a problem.

    In a brainstorming session there are no "bad" ideas. The aim is to generate ideas; not to validate them. Brainstorming encourages you to "think outside the box" and put "crazy" ideas on the table without fear of rejection.

    What is the key characteristic about brainstorming?

    (b)

    [W4.1f] Requirements → Gathering Requirements → Product Surveys

    Can explain product surveys

    Studying existing products can unearth shortcomings of existing solutions that can be addressed by a new product. Product manuals and other forms of technical documentation of an existing system can be a good way to learn about how the existing solutions work.

    When developing a game for a mobile device, a look at a similar PC game can give insight into the kind of features and interactions the mobile game can offer.

    [W4.1g] Requirements → Gathering Requirements → Observation

    Can explain observation

    Observing users in their natural work environment can uncover product requirements. Usage data of an existing system can also be used to gather information about how an existing system is being used, which can help in building a better replacement  e.g. to find the situations where the user makes mistakes when using the current system.

    [W4.1h] Requirements → Gathering Requirements → User Surveys

    Can explain user surveys

    Surveys can be used to solicit responses and opinions from a large number of stakeholders regarding a current product or a new product.

    [W4.1i] Requirements → Gathering Requirements → Interviews

    Can explain interviews

    Interviewing stakeholders and domain experts can produce useful information that project requirements.

     

    Domain Expert : An expert of a discipline to which the product is connected  e.g., for a software used for Accounting, a domain expert is someone who is an expert of Accounting.

    [W4.1j] Requirements → Gathering Requirements → Focus Groups

    Can explain focus groups


    [source]

    Focus groups are a kind of informal interview within an interactive group setting. A group of people (e.g. potential users, beta testers) are asked about their understanding of a specific issue, process, product, advertisement, etc.

    : How do focus groups work? - Hector Lanz tangential
    [W4.1k] Requirements → Gathering Requirements → Prototyping

    Can explain prototyping

    Prototype: A prototype is a mock up, a scaled down version, or a partial system constructed

    • to get users’ feedback.
    • to validate a technical concept (a "proof-of-concept" prototype).
    • to give a preview of what is to come, or to compare multiple alternatives on a small scale before committing fully to one alternative.
    • for early field-testing under controlled conditions.

    Prototyping can uncover requirements, in particular, those related to how users interact with the system. UI prototypes are often used in brainstorming sessions, or in meetings with the users to get quick feedback from them.

    [source: http://balsamiq.com/products/mockups]

    💡 Prototyping can be used for discovering as well as specifying requirements  e.g. a UI prototype can serve as a specification of what to build.


    Specifying Requirements

    [W4.1l] Requirements → Specifying Requirements → Prose → What

    Can explain prose

    A textual description (i.e. prose) can be used to describe requirements. Prose is especially useful when describing abstract ideas such as the vision of a product.

    The product vision of the TEAMMATES Project given below is described using prose.

    TEAMMATES aims to become the biggest student project in the world (biggest here refers to 'many contributors, many users, large code base, evolving over a long period'). Furthermore, it aims to serve as a training tool for Software Engineering students who want to learn SE skills in the context of a non-trivial real software product.

    Avoid using lengthy prose to describe requirements; they can be hard to follow.

    [W4.1m] Requirements → Specifying Requirements → Feature Lists → What

    Can explain feature list

    Feature List: A list of features of a product grouped according to some criteria such as aspect, priority, order of delivery, etc.

    A sample feature list from a simple Minesweeper game  (only a brief description has been provided to save space):

    1. Basic play – Single player play.
    2. Difficulty levels
      • Medium-levels
      • Advanced levels
    3. Versus play – Two players can play against each other.
    4. Timer – Additional fixed time restriction on the player.
    5. ...
    [W4.1n] Requirements → Specifying Requirements → User Stories → Introduction

    Can write simple user stories

    User story: User stories are short, simple descriptions of a feature told from the perspective of the person who desires the new capability, usually a user or customer of the system. [Mike Cohn]

    A common format for writing user stories is:

    User story format: As a {user type/role} I can {function} so that {benefit}

    Examples (from a Learning Management System):

    1. As a student, I can download files uploaded by lecturers, so that I can get my own copy of the files
    2. As a lecturer, I can create discussion forums, so that students can discuss things online
    3. As a tutor, I can print attendance sheets, so that I can take attendance during the class

    We can write user stories on index cards or sticky notes, and arrange on walls or tables, to facilitate planning and discussion. Alternatively, we can use a software (e.g., GitHub Project Boards, Trello, Google Docs, ...) to manage user stories digitally.

    [credit: https://www.flickr.com/photos/jakuza/2682466984/]

    [credit: https://www.flickr.com/photos/jakuza/with/2726048607/]

    [credit: https://commons.wikimedia.org/wiki/File:User_Story_Map_in_Action.png]

    • a. They are based on stories users tell about similar systems
    • b. They are written from the user/customer perspective
    • c. They are always written in some physical medium such as index cards or sticky notes
    • a. Reason: Despite the name, user stories are not related to 'stories' about the software.
    • b.
    • c. Reason: It is possible to use software to record user stories. When the team members are not co-located this may be the only option.

    Critique the following user story taken from a software project to build an e-commerce website.

    As a developer, I want to use Python to implement the software, so that we can resue existing Python modules.

    Refer to the definition of a user story.

    User story: User stories are short, simple descriptions of a feature told from the perspective of the person who desires the new capability, usually a user or customer of the system. [Mike Cohn]

    This user story is not written from the perspective of the user/customer.

    Bill wants you to build a Human Resource Management (HRM) system. He mentions that the system will help employees to view their own leave balance. What are the user stories you can extract from that statement?

    Remember to follow the correct format when writing user stories.

    User story format: As a {user type/role} I can {function} so that {benefit}

    As an employee, I can view my leave balance, so that I can know how many leave days I have left.

    Note: the {benefit} part may vary as it is not specifically mentioned in the question.

    [W4.1o] Requirements → Specifying Requirements → User Stories → Details

    Can write more detailed user stories

    The {benefit} can be omitted if it is obvious.

    As a user, I can login to the system so that I can access my data

    💡 It is recommended to confirm there is a concrete benefit even if you omit it from the user story. If not, you could end up adding features that have no real benefit.

    You can add more characteristics to the {user role} to provide more context to the user story.

    • As a forgetful user, I can view a password hint, so that I can recall my password.
    • As an expert user, I can tweak the underlying formatting tags of the document, so that I can format the document exactly as I need.

    You can write user stories at various levels. High-level user stories, called epics (or themes) cover bigger functionality. You can then break down these epics to multiple user stories of normal size.

    [Epic] As a lecturer, I can monitor student participation levels

    • As a lecturer, I can view the forum post count of each student so that I can identify the activity level of students in the forum
    • As a lecturer, I can view webcast view records of each student so that I can identify the students who did not view webcasts
    • As a lecturer, I can view file download statistics of each student so that I can identify the students who do not download lecture materials

    You can add conditions of satisfaction to a user story to specify things that need to be true for the user story implementation to be accepted as ‘done’.

    • As a lecturer, I can view the forum post count of each student so that I can identify the activity level of students in the forum.

    Conditions:

    • Separate post count for each forum should be shown
    • Total post count of a student should be shown
    • The list should be sortable by student name and post count

    Other useful info that can be added to a user story includes (but not limited to)

    • Priority: how important the user story is
    • Size: the estimated effort to implement the user story
    • Urgency: how soon the feature is needed
    More examples tangential

    User stories for a travel website (credit: Mike Cohen)

    • As a registered user, I am required to log in so that I can access the system
    • As a forgetful user, I can request a password reminder so that I can log in if I forget mine
    • [Epic] As a user, I can cancel a reservation
      • As a premium site member, I can cancel a reservation up to the last minute
      • As a non-premium member, I can cancel up to 24 hours in advance
      • As a member, I am emailed a confirmation of any cancelled reservation
    • [Epic] As a frequent flyer, I want to book a trip
      • As a frequent flyer, I want to book a trip using miles
      • As a frequent flyer, I want to rebook a trip I take often
      • As a frequent flyer, I want to request an upgrade
      • As a frequent flyer, I want to see if my upgrade cleared

    Choose the correct statements

    • a. User stories are short and written in a formal notation.
    • b. User stories is another name for use cases.
    • c. User stories describes past experiences users had with similar systems. These are helpful in developing the new system.
    • d. User stories are not detailed enough to tell us exact details of the product.
    • a.
    • b.
    • c.
    • d.

    Explanation: User stories are short and written in natural language, NOT in a formal language. They are used for estimation and scheduling purposes but do not contain enough details to form a complete system specification.

    [W4.1p] Requirements → Specifying Requirements → User Stories → Usage

    Can use user stories to manage requirements of project

    User stories capture user requirements in a way that is convenient for scoping, estimation and scheduling.

    [User stories] strongly shift the focus from writing about features to discussing them. In fact, these discussions are more important than whatever text is written. [Mike Cohn, MountainGoat Software 🔗]

    User stories differ from traditional requirements specifications mainly in the level of detail. User stories should only provide enough details to make a reasonably low risk estimate of how long the user story will take to implement. When the time comes to implement the user story, the developers will meet with the customer face-to-face to work out a more detailed description of the requirements. [more...]

    User stories can capture non-functional requirements too because even NFRs must benefit some stakeholder.

     

    Requirements → Requirements →

    Non-Functional Requirements

    There are two kinds of requirements:

    1. Functional requirements specify what the system should do.
    2. Non-functional requirements specify the constraints under which system is developed and operated.

    Some examples of non-functional requirement categories:

    • Data requirements e.g. size, volatility, persistency etc.,
    • Environment requirements e.g. technical environment in which system would operate or need to be compatible with.
    • Accessibility, Capacity, Compliance with regulations, Documentation, Disaster recovery, Efficiency, Extensibility, Fault tolerance, Interoperability, Maintainability, Privacy, Portability, Quality, Reliability, Response time, Robustness, Scalability, Security, Stability, Testability, and more ...
    • Business/domain rules: e.g. the size of the minefield cannot be smaller than five.
    • Constraints: e.g. the system should be backward compatible with data produced by earlier versions of the system; system testers are available only during the last month of the project; the total project cost should not exceed $1.5 million.
    • Technical requirements: e.g. the system should work on both 32-bit and 64-bit environments.
    • Performance requirements: e.g. the system should respond within two seconds.
    • Quality requirements: e.g. the system should be usable by a novice who has never carried out an online purchase.
    • Process requirements: e.g. the project is expected to adhere to a schedule that delivers a feature set every one month.
    • Notes about project scope: e.g. the product is not required to handle the printing of reports.
    • Any other noteworthy points: e.g. the game should not use images deemed offensive to those injured in real mine clearing activities.

    We may have to spend an extra effort in digging NFRs out as early as possible because,

    1. NFRs are easier to miss  e.g., stakeholders tend to think of functional requirements first
    2. sometimes NFRs are critical to the success of the software.  E.g. A web application that is too slow or that has low security is unlikely to succeed even if it has all the right functionality.

    Given below are some requirements of TEAMMATES (an online peer evaluation system for education). Which one of these are non-functional requirements?

    • a. The response to any use action should become visible within 5 seconds.
    • b. The application admin should be able to view a log of user activities.
    • c. The source code should be open source.
    • d. A course should be able to have up to 2000 students.
    • e. As a student user, I can view details of my team members so that I can know who they are.
    • f. The user interface should be intuitive enough for users who are not IT-savvy.
    • g. The product is offered as a free online service.

    (a)(c)(d)(f)(g)

    Explanation: (b) are (e) are functions available for a specific user types. Therefore, they are functional requirements. (a), (c), (d), (f) and (g) are either constraints on functionality or constraints on how the project is done, both of which are considered non-functional requirements.

    An example of a NFR captured as a user story:

    As a I want to so that
    impatient user to be able experience reasonable response time from the website while up to 1000 concurrent users are using it I can use the app even when the traffic is at the maximum expected level

    Given their lightweight nature, user stories are quite handy for recording requirements during early stages of requirements gathering.

    💡 Here are some tips for using user stories for early stages of requirement gathering:

    • Define the target user:
      Decide your target user's profile (e.g. a student, office worker, programmer, sales person) and work patterns (e.g. Does he work in groups or alone? Does he share his computer with others?). A clear understanding of the target user will help when deciding the importance of a user story. You can even give this user a name.  e.g. Target user Jean is a university student studying in a non-IT field. She interacts with a lot of people due to her involvement in university clubs/societies. ...
    • Define the problem scope: Decide that exact problem you are going to solve for the target user.  e.g. Help Jean keep track of all her school contacts
    • Don't be too hasty to discard 'unusual' user stories:
      Those might make your product unique and stand out from the rest, at least for the target users.
    • Don't go into too much details:
      For example, consider this user story: As a user, I want to see a list of tasks that needs my attention most at the present time, so that I pay attention to them first.
      When discussing this user story, don't worry about what tasks should be considered needs my attention most at the present time. Those details can be worked out later.
    • Don't be biased by preconceived product ideas:
      When you are at the stage of identifying user needs, clear your mind of ideas you have about what your end product will look like.
    • Don't discuss implementation details or whether you are actually going to implement it:
      When gathering requirements, your decision is whether the user's need is important enough for you to want to fulfil it. Implementation details can be discussed later. If a user story turns out to be too difficult to implement later, you can always omit it from the implementation plan.

    While use cases can be recorded on physical paper in the initial stages, an online tool is more suitable for longer-term management of user stories, especially if the team is not co-located.

     

    You can create issues for each of the user stories and use a GitHub Project Board to sort them into categories.

    Example Project Board:

    Example Issue to represent a user story:

    A video on GitHub Project Boards:


     

    Example Google Sheet for recording user stories:


     

    Example Trello Board for recording user stories:


    eXtreme Programming (XP)

    Extreme programming (XP) is a software development methodology which is intended to improve software quality and responsiveness to changing customer requirements. As a type of agile software development, it advocates frequent "releases" in short development cycles, which is intended to improve productivity and introduce checkpoints at which new customer requirements can be adopted. [wikipedia, 2017.05.01]

    uses User stories to capture requirements.

    This page in their website explains the difference between user stories and traditional requirements.

    One of the biggest misunderstandings with user stories is how they differ from traditional requirements specifications. The biggest difference is in the level of detail. User stories should only provide enough detail to make a reasonably low risk estimate of how long the story will take to implement. When the time comes to implement the story developers will go to the customer and receive a detailed description of the requirements face to face.

    [W4.1undefined] Requirements → Specifying Requirements → Use Cases → Introduction

    Can explain use cases

    Use Case: A description of a set of sequences of actions, including variants, that a system performs to yield an observable result of value to an actor.[ 📖 : uml-user-guideThe Unified Modeling Language User Guide, 2e, G Booch, J Rumbaugh, and I Jacobson ]

    Actor: An actor (in a use case) is a role played by a user. An actor can be a human or another system. Actors are not part of the system; they reside outside the system.

    A use case describes an interaction between the user and the system for a specific functionality of the system.

    • System: ATM
    • Actor: Customer
    • Use Case: Check account balance
      1. User inserts an ATM card
      2. ATM prompts for PIN
      3. User enters PIN
      4. ATM prompts for withdrawal amount
      5. User enters the amount
      6. ATM ejects the ATM card and issues cash
      7. User collects the card and the cash.
    • System: A Learning Management System (LMS)
    • Actor: Student
    • Use Case: Upload file
      1. Student requests to upload file
      2. LMS requests for the file location
      3. Student specifies the file location
      4. LMS uploads the file

    UML includes a diagram type called use case diagrams that can illustrate use cases of a system visually , providing a visual ‘table of contents’ of the use cases of a system. In the example below, note how use cases are shown as ovals and user roles relevant to each use case are shown as stick figures connected to the corresponding ovals.

    Unified Modeling Language (UML) is a graphical notation to describe various aspects of a software system. UML is the brainchild of three software modeling specialists James Rumbaugh, Grady Booch and Ivar Jacobson (also known as the Three Amigos). Each of them has developed their own notation for modeling software systems before joining force to create a unified modeling language (hence, the term ‘Unified’ in UML). UML is currently the de facto modeling notation used in the software industry.

    Use cases capture the functional requirements of a system.

    [W4.1undefined] Requirements → Specifying Requirements → Use Cases → Identifying

    Can use use cases to list functional requirements of a simple system

    A use case is an interaction between a system and its actors.

    Actors in Use Cases

    Actor: An actor (in a use case) is a role played by a user. An actor can be a human or another system. Actors are not part of the system; they reside outside the system.

    Some example actors for a Learning Management System

    • Actors: Guest, Student, Staff, Admin, ExamSys, LibSys.

    A use case can involve multiple actors.

    • Software System: LearnSys
    • Use case: UC01 conduct survey
    • Actors: Staff, Student

    An actor can be involved in many use cases.

    • Software System: LearnSys
    • Actor: Staff
    • Use cases: UC01 conduct survey, UC02 Set Up Course Schedule, UC03 Email Class, ...

    A single person/system can play many roles.

    • Software System: LearnSys
    • Person: a student
    • Actors (or Roles): Student, Guest, Tutor

    Many persons/systems can play a single role.

    • Software System: LearnSys
    • Actor(or role) : Student
    • Persons that can play this role : undergraduate student, graduate student, a staff member doing a part-time course, exchange student

    Use cases can be specified at various levels of detail.

    Consider the three use cases given below. Clearly, (a) is at a higher level than (b) and (b) is at a higher level than (c).

    • System: LearnSys
    • Use cases:
      a. Conduct a survey
      b. Take the survey
      c. Answer survey question

    💡 While modeling user-system interactions,

    • Start with high level use cases and progressively work toward lower level use cases.
    • Be mindful at which level of details you are working on and not to mix use cases of different levels.

    Consider a simple movie ticket vending machine application. Every week, the theatre staff will enter the weekly schedule as well as ticket price for each show. A customer sees the schedule and the ticket price displayed at the machine. There is a slot to insert money, a keypad to enter a code for a movie, a code for the show time, and the number of tickets. A display shows the customer's balance inside the machine. A customer may choose to cancel a transaction before pressing the “buy” button. Printed tickets can be collected from a slot at the bottom of the machine. The machine also displays messages such as "Please enter more money”, “Request fewer tickets" or "SOLD OUT!”. Finally, a "Return Change" button allows the customer to get back his unspent money.

    Draw a use case diagram for the above requirements.

    Note that most of the details in the description are better given as part of the use case description rather than as low-level use cases in the diagram.

    A software house wishes to automate its Quality Assurance division.

    The system is to be used by Testers, Programmers and System Administrators. Only an administrator can create new users and assign tasks to programmers. Any tester can create a bug report, as well as set the status of a bug report as ‘closed’. Only a programmer can set the state of a bug report to ‘fixed’, but a programmer cannot set the status of a bug report to ‘closed’. Each tester is assigned just one task at a time. A task involves testing of a particular component for a particular customer. Tester must document the bugs they find. Each bug is given a unique identifier. Other information recorded about the bug is component id, severity, date and time reported, programmer who is assigned to fix it, date fixed, date retested and date closed. The system keeps track of which bugs are assigned to which programmer at any given time. It should be able to generate reports on the number of bugs found, fixed and closed e.g. number of bugs per component and per customer; number of bugs found by a particular tester ; number of bugs awaiting to be fixed; number of bugs awaiting to be retested; number of bugs awaiting to be assigned to programmers etc.

    Develop a use case diagram to capture their requirements given below.

    Explanation: The given description contains information not relevant to use case modeling. Furthermore, the description is not enough to complete the use case diagram All these are realities of real projects. However, the process of trying to create this use case diagram prompts us to investigate issues such as:

    • Is ‘edit bug report’ a use case or editing the bug report is covered by other use cases such as those for setting the status of bug reports? If it is indeed a separate use case, who are the actors of that use case?
    • Does ‘assign task’ simply means ‘assign bug report’ or is there any other type of tasks?
    • There was some mention about Customers and Components. Does the system have to support use cases for creating and maintaining details about those entities? For example, should we have a ‘create customer record’ use case?
    • Which actors can perform the ‘generate report’ use case? Are reports generated automatically by the system at a specific time or generated ‘on demand’ when users request to view them? Do we have to treat different types of reports as different use cases (in case some types of reports are restricted to some types of users)? The above diagram assumes (just for illustration) that the report is generated on demand and only the system admin can generate any report.
    [W4.1undefined] Requirements → Specifying Requirements → Use Cases → Details

    Can specify details of a use case in a structured format

    Writing use case steps

    The main body of the use case is the sequence of steps that describes the interaction between the system and the actors. Each step is given as a simple statement describing who does what.

    An example of the main body of a use case.

    1. Student requests to upload file
    2. LMS requests for the file location
    3. Student specifies the file location
    4. LMS uploads the file

    A use case describes only the externally visible behavior, not internal details, of a system i.e. should not mention give details that are not part of the interaction between the user and the system.

    This example use case step refers to behaviors not externally visible .

    1. LMS saves the file into the cache and indicates success.

    A step gives the intention of the actor (not the mechanics). That means UI details are usually omitted. The idea is to leave as much flexibility to the UI designer as possible. That is, the use case specification should be as general as possible (less specific) about the UI.

    The first example below is not a good use case step because contains UI-specific details. The second one is better because it omits UI-specific details.

    Bad : User right-clicks the text box and chooses ‘clear’

    Good : User clears the input

    A use case description can show loops too.

    An example of how you can show a loop:

    Software System: Square game Use case: UC02 - Play a Game Actors: Player (multiple players)

    1. A Player starts the game.
    2. SquareGame asks for player names.
    3. Each Player enters his own name.
    4. SquareGame shows the order of play.
    5. SquareGame prompts for the current Player to throw die.
    6. Current Player adjusts the throw speed.
    7. Current Player triggers the die throw.
    8. Square Game shows the face value of the die.
    9. Square Game moves the Player's piece accordingly.
      Steps 5-9 are repeated for each Player, and for as many rounds as required until a Player reaches the 100th square.
    10. Square Game shows the Winner.

      Use case ends.

    The Main Success Scenario (MSS) describes the most straightforward interaction for a given use case, which assumes that nothing goes wrong. This is also called the Basic Course of Action or the Main Flow of Events of a use case.

    • System: Online Banking System (OBS)
    • Use case: UC23 - Transfer Money
    • Actor: User
    • MSS:
      1. User chooses to transfer money.
      2. OBS requests for details of the transfer.
      3. User enters the requested details.
      4. OBS requests for confirmation.
      5. OBS transfers the money and displays the new account balance.
      6. Use case ends.

    Note how the MSS assumes that all entered details are correct and ignores problems such as timeouts, network outages etc. Fro example, MSS does not tell us what happens if the user enters an incorrect data.

    Extensions are "add-on"s to the MSS that describe exceptional/alternative flow of events. They describe variations of the scenario that can happen if certain things are not as expected by the MSS. Extensions appear below the MSS.

    This example adds some extensions to the use case in the previous example.

    • System: Online Banking System (OBS)
    • Use case: UC23 - Transfer Money
    • Actor: User
    • MSS:
      1. User chooses to transfer money.
      2. OBS requests for details of the transfer.
      3. User enters the requested details.
      4. OBS requests for confirmation.
      5. OBS transfers the money and displays the new account balance.
      6. Use case ends.

    • Extensions:
      1. 3a. OBS detects an error in the entered data.
        1. 3a1. OBS requests for the correct data.
        2. 3a2. User enters new data.
        3. Steps 3a1-3a2 are repeated until the data entered are correct.
        4. Use case resumes from step 4.

      2. 3b. User requests to effect the transfer in a future date.
        1. 3b1. OBS requests for confirmation.
        2. 3b2. User confirms future transfer.
        3. Use case ends.

      3. *a. At any time, User chooses to cancel the transfer.
        1. *a1. OBS requests to confirm the cancellation.
        2. *a2. User confirms the cancellation.
        3. Use case ends.

      4. *b. At any time, 120 seconds lapse without any input from the User.
        1. *b1. OBS cancels the transfer.
        2. *b2. OBS informs the User of the cancellation.
        3. Use case ends.

    Note that the numbering style is not a universal rule but a widely used convention. Based on that convention,

    • either of the extensions marked 3a. and 3b. can happen just after step 3 of the MSS.
    • the extension marked as *a. can happen at any step (hence, the *).

    When separating extensions from the MSS, keep in mind that the MSS should be self-contained. That is, the MSS should give us a complete usage scenario.

    Also note that it is not useful to mention events such as power failures or system crashes as extensions because the system cannot function beyond such catastrophic failures.

    In use case diagrams you can use the <<extend>> arrows to show extensions. Note the direction of the arrow is from the extension to the use case it extends and the arrow uses a dashed line.

    A use case can include another use case. Underlined text is commonly used to show an inclusion of a use case.

    This use case includes two other use cases, one in step 1 and one in step 2.

    • Software System: LearnSys
    • Use case: UC01 - Conduct Survey
    • Actors: Staff, Student
    • MSS:
      1. Staff creates the survey (UC44).
      2. Student completes the survey (UC50).
      3. Staff views the survey results.
        Use case ends.

    Inclusions are useful,

    • when you don't want to clutter a use case with too many low-level steps.
    • when a set of steps is repeated in multiple use cases.

    We use a dotted arrow and a <<include>> annotation to show use case inclusions in a use case diagram. Note how the arrow direction is different from the <<extend>> arrows.

    Preconditions specify the specific state we expect the system to be in before the use case starts.

    • Software System: Online Banking System
    • Use case: UC23 - Transfer Money
    • Actor: User
    • Preconditions: User is logged in.
    • MSS:
      1. User chooses to transfer money.
      2. OBS requests for details for the transfer.
      3. ...

    Guarantees specify what the use case promises to give us at the end of its operation.

    • Software System: Online Banking System
    • Use case: UC23 - Transfer Money
    • Actor: User
    • Preconditions: User is logged in.
    • Guarantees:
      • Money will be deducted from the source account only if the transfer to the destination account is successful
      • The transfer will not result in the account balance going below the minimum balance required.
    • MSS:
      1. User chooses to transfer money.
      2. OBS requests for details for the transfer.
      3. ...

    Complete the following use case (MSS, extensions, etc.). Note that you should not blindly follow how the existing EZ-Link machine operates because it will prevent you from designing a better system. You should consider all possible extensions without complicating the use case too much.

    • System: EZ-Link machine
    • Use case: UC2 top-up EZ-Link card
    • Actor: EZ-Link card user
    • System: EZ-Link machine (those found at MRTs)
    • Use case: UC2 top-up EZ-Link card
    • Actor: EZ-Link card user
    • Preconditions: All hardware in working order.
    • Guarantees: MSS → the card will be topped-up.
    • MSS:
      1. User places the card on the reader.
      2. System displays card details and prompts for desired action.
      3. User selects top-up.
      4. System requests for top-up details (amount, payment option, receipt required?).
      5. User enters details.
      6. System processes cash payment (UC02) or NETS payment (UC03).
      7. System updates the card value.
      8. System indicates transaction as completed.
      9. If requested in step 5, system prints receipt.
      10. User removes the card.
      11. Use case ends.
    • Extensions:
      1. *a. User removed card or other hardware error detected.
        1. *a1. System indicates the transaction has been aborted.
        2. Use case ends.

    Notes:

    • We assume that the only way to cancel a transaction is by removing the card.
    • By not breaking step 4 into further steps, we avoid committing to a particular mechanism to enter data. For example, we are free to accept all data in one screen.
    • In step 5, we assume that the input mechanism does not allow any incorrect data.
    • System: EZ-Link machine
    • Use case: UC03 process NETS payment
    • Actor: EZ-Link card user
    • Preconditions: A transaction requiring payment is underway.
    • Guarantees: MSS → Transaction amount is transferred from user account to EZ-Link company account.
    • MSS:
      1. System requests to insert ATM card.
      2. User inserts the ATM card.
      3. System requests for PIN.
      4. User enters PIN.
      5. System reports success.
      6. Use case ends.
    • Extensions:
      1. 2a. Unacceptable ATM card (damaged or inserted wrong side up).
        1. ...
      2. 4a. Wrong PIN.
        1. ...
      3. 4b. Insufficient funds.
        1. ...
      4. *a. Connection to the NETS gateway is disrupted.
        1. ...

    Note: UC02 can be written along similar lines.

    Complete the following use case (MSS, extensions, etc.).

    • System: LearnSys (an online Learning Management System)
    • Use case: UC01 reply to post in the forum
    • Actor: Student
    • System: LearnSys
    • Use case: UC01 reply to post in the forum
    • Actor: Student
    • Preconditions: Student is logged in and has permission to post in the forum. The post to which the Student replies already exists.
    • MSS:
      1. Student chooses to reply to an existing post.
      2. LearnSys requests the user to enter post details.
      3. Student enters post details.
      4. Student submits the post.
      5. LearnSys displays the post.
      6. Use case ends.
    • Extensions:
      1. *a. Internet connection goes down.
        1. ...
      2. *b. LearnSys times out
        1. ...
      3. 3a. Student chooses to ‘preview’ the post.
        1. 3a1. LearnSys shows a preview.
        2. 3a2. User chooses to go back to editing.
        3. Use case resumes at step 3.
      4. 3b. Student chooses to attach picture/file
        1. ...
      5. 3c. Student chooses to save the post as a draft.
        1. 3c1. LearnSys confirms draft has been saved.
        2. Use case ends.
      6. 3d. Student chooses to abort the operation.
        1. ...
      7. 4a. The post being replied to is deleted by the owner while the reply is being entered.
        1. ...
      8. 4b. Unacceptable data entered.
        1. ...

    Which of these cannot appear as part of a use case description?

    • a. Use case identifier
    • b. Preconditions
    • c. Guarantees
    • d. References to another use case
    • e. Main Success Scenario
    • f. Performance requirements
    • g. Extensions
    • h. Inclusions

    (f)

    Explanation: Performance requirements are non-functional requirements. They are not captured in use cases.

    Identify problems with this use case description.

    • System: EZ-Link machine (those found at MRTs)
    • Use case: UC2 top-up EZ-Link card
    • Actor: EZ-Link card user
    • Preconditions: All hardware in working order.
    • Guarantees: If MSS completes at least until step 7, the card will be topped-up.
    • MSS:
      1. User places the card on the reader.
      2. System displays card details and prompts for desired action.
      3. User selects top-up.
      4. System requests for top-up details (amount, payment option, receipt required?).
      5. User enters details.
      6. System processes cash payment (UC02) or NETS payment (UC03).
      7. System updates the card value.
      8. System indicates transaction as completed.
      9. If requested in step 5, system prints receipt.
      10. User removes the card.
      11. Use case ends.
    • Extensions:
      1. *a. User removed card or other hardware error detected.
        1. *a1. System indicates the transaction has been aborted.
        2. Use case ends.
    • a. It does not consider ‘system crash’ scenario.
    • b. It does not contain enough UI details.
    • c. The extension given is in fact an inclusion.
    • d. No post conditions are given.
    • e. ‘Use case ends’ is duplicated.

    None.

    Explanation: Catastrophic failures such as ‘system crash’ need not be included in a use case. A use case is not supposed to contain UI details. Post conditions are optional. It is not a problem to have multiple exit points for a use case.

    [W4.1undefined] Requirements → Specifying Requirements → Use Cases → Usage

    Can optimize the use of use cases

    You can use actor generalization in use case diagrams using a symbol similar to that of UML notation for inheritance.

    In this example, actor Blogger can do all the use cases the actor Guest can do, as a result of the actor generalization relationship given in the diagram.

    💡 Do not over-complicate use case diagrams by trying to include everything possible. A use case diagram is a brief summary of the use cases that is used as a starting point. Details of the use cases can be given in the use case descriptions.

    Some include ‘System’ as an actor to indicate that something is done by the system itself without being initiated by a user or an external system.

    The diagram below can be used to indicate that the system generates daily reports at midnight.

    However, others argue that only use cases providing value to an external user/system should be shown in the use case diagram. For example, they argue that ‘view daily report’ should be the use case and generate daily report is not to be shown in the use case diagram because it is simply something the system has to do to support the view daily report use case.

    We recommend that you follow the latter view (i.e. not to use System as a user). Limit use cases for modeling behaviors that involve an external actor.

    UML is not very specific about the text contents of a use case. Hence, there are many styles for writing use cases. For example, the steps can be written as a continuous paragraph. Use cases should be easy to read. Note that there is no strict rule about writing all details of all steps or a need to use all the elements of a use case.

    There are some advantages of documenting system requirements as use cases:

    • Because they use a simple notation and plain English descriptions, they are easy for users to understand and give feedback.
    • They decouple user intention from mechanism (note that use cases should not include UI-specific details), allowing the system designers more freedom to optimize how a functionality is provided to a user.
    • Identifying all possible extensions encourages us to consider all situations that a software product might face during its operation.
    • Separating typical scenarios from special cases encourages us to optimize the typical scenarios.

    One of the main disadvantages of use cases is that they are not good for capturing requirements that does not involve a user interacting with the system. Hence, they should not be used as the sole means to specify requirements.

    What are the advantages of using use cases (the textual form) for requirements modelling?

    • a. They can be fairly detailed but still natural enough for users for users to understand and give feedback.
    • b. The UI-independent nature of use case specification allows the system designers more freedom to decide how a functionality is provided to a user.
    • c. Extensions encourage us to consider all situations a software product might face during its operations.
    • d. They encourage us to identify and optimize the typical scenario of usage over exceptional usage scenarios.

    (a) (b) (c) (d)

    Which of these are correct?

    • a. Use case are not very suitable for capturing non-functional requirements.
    • b. Use case diagrams are less detailed than textual use cases.
    • c. Use cases are better than user stories.
    • d. Use cases can be expressed at different levels of abstraction.

    (a)(b)(d)

    Explanation: It is not correct to say one format is better than the other. It depends on the context.

    [W4.1undefined] Requirements → Specifying Requirements → Glossary → What

    Can explain glossary

    Glossary: A glossary serves to ensure that all stakeholders have a common understanding of the noteworthy terms, abbreviation, acronyms etc.

    Here is a partial glossary from a variant of the Snakes and Ladders game:

    • Conditional square: A square that specifies a specific face value which a player has to throw before his/her piece can leave the square.
    • Normal square: a normal square does not have any conditions, snakes, or ladders in it.
    [W4.1undefined] Requirements → Specifying Requirements → Supplementary Requirements → What

    Can explain supplementary requirements

    A supplementary requirements section can be used to capture requirements that do not fit elsewhere. Typically, this is where most Non Functional Requirements will be listed.

     

    Requirements → Requirements →

    Non-Functional Requirements

    There are two kinds of requirements:

    1. Functional requirements specify what the system should do.
    2. Non-functional requirements specify the constraints under which system is developed and operated.

    Some examples of non-functional requirement categories:

    • Data requirements e.g. size, volatility, persistency etc.,
    • Environment requirements e.g. technical environment in which system would operate or need to be compatible with.
    • Accessibility, Capacity, Compliance with regulations, Documentation, Disaster recovery, Efficiency, Extensibility, Fault tolerance, Interoperability, Maintainability, Privacy, Portability, Quality, Reliability, Response time, Robustness, Scalability, Security, Stability, Testability, and more ...
    • Business/domain rules: e.g. the size of the minefield cannot be smaller than five.
    • Constraints: e.g. the system should be backward compatible with data produced by earlier versions of the system; system testers are available only during the last month of the project; the total project cost should not exceed $1.5 million.
    • Technical requirements: e.g. the system should work on both 32-bit and 64-bit environments.
    • Performance requirements: e.g. the system should respond within two seconds.
    • Quality requirements: e.g. the system should be usable by a novice who has never carried out an online purchase.
    • Process requirements: e.g. the project is expected to adhere to a schedule that delivers a feature set every one month.
    • Notes about project scope: e.g. the product is not required to handle the printing of reports.
    • Any other noteworthy points: e.g. the game should not use images deemed offensive to those injured in real mine clearing activities.

    We may have to spend an extra effort in digging NFRs out as early as possible because,

    1. NFRs are easier to miss  e.g., stakeholders tend to think of functional requirements first
    2. sometimes NFRs are critical to the success of the software.  E.g. A web application that is too slow or that has low security is unlikely to succeed even if it has all the right functionality.

    Given below are some requirements of TEAMMATES (an online peer evaluation system for education). Which one of these are non-functional requirements?

    • a. The response to any use action should become visible within 5 seconds.
    • b. The application admin should be able to view a log of user activities.
    • c. The source code should be open source.
    • d. A course should be able to have up to 2000 students.
    • e. As a student user, I can view details of my team members so that I can know who they are.
    • f. The user interface should be intuitive enough for users who are not IT-savvy.
    • g. The product is offered as a free online service.

    (a)(c)(d)(f)(g)

    Explanation: (b) are (e) are functions available for a specific user types. Therefore, they are functional requirements. (a), (c), (d), (f) and (g) are either constraints on functionality or constraints on how the project is done, both of which are considered non-functional requirements.

    [W4.2] CodeQuality


    Readability

    [W4.2a] Implementation → Code Quality → Readability → Introduction

    Can explain the importance of readability

    Programs should be written and polished until they acquire publication quality. --Niklaus Wirth

    Among various dimensions of code quality, such as run-time efficiency, security, and robustness, one of the most important is understandability. This is because in any non-trivial software project, code needs to be read, understood, and modified by other developers later on. Even if we do not intend to pass the code to someone else, code quality is still important because we all become 'strangers' to our own code someday.

    The two code samples given below achieve the same functionality, but one is easier to read.

         

    Bad

    int subsidy() {
        int subsidy;
        if (!age) {
            if (!sub) {
                if (!notFullTime) {
                    subsidy = 500;
                } else {
                    subsidy = 250;
                }
            } else {
                subsidy = 250;
            }
        } else {
            subsidy = -1;
        }
        return subsidy;
    }
    

      

    Good

    int calculateSubsidy() {
        int subsidy;
        if (isSenior) {
            subsidy = REJECT_SENIOR;
        } else if (isAlreadySubsidised) {
            subsidy = SUBSIDISED_SUBSIDY;
        } else if (isPartTime) {
            subsidy = FULLTIME_SUBSIDY * RATIO;
        } else {
            subsidy = FULLTIME_SUBSIDY;
        }
        return subsidy;
    }
    

         

    Bad

    def calculate_subs():
        if not age:
            if not sub:
                if not not_fulltime:
                    subsidy = 500
                else:
                    subsidy = 250
            else:
                subsidy = 250
        else:
            subsidy = -1
        return subsidy
    

      

    Good

    def calculate_subsidy():
        if is_senior:
            return REJECT_SENIOR
        elif is_already_subsidised:
            return SUBSIDISED_SUBSIDY
        elif is_parttime:
            return FULLTIME_SUBSIDY * RATIO
        else:
            return FULLTIME_SUBSIDY
    

    [W4.2b] Implementation → Code Quality → Readability → Basic → Avoid Long Methods

    Can improve code quality using technique: avoid long methods

    Be wary when a method is longer than the computer screen, and take corrective action when it goes beyond 30 LOC (lines of code). The bigger the haystack, the harder it is to find a needle.

    [W4.2c] Implementation → Code Quality → Readability → Basic → Avoid Deep Nesting

    Can improve code quality using technique: avoid deep nesting

    If you need more than 3 levels of indentation, you're screwed anyway, and should fix your program. --Linux 1.3.53 CodingStyle

    In particular, avoid arrowhead style code.

    Example:

    [W4.2d] Implementation → Code Quality → Readability → Basic → Avoid Complicated Expressions

    Can improve code quality using technique: avoid complicated expressions

    Avoid complicated expressions, especially those having many negations and nested parentheses. If you must evaluate complicated expressions, have it done in steps (i.e. calculate some intermediate values first and use them to calculate the final value).

    Example:

    Bad

    return ((length < MAX_LENGTH) || (previousSize != length)) && (typeCode == URGENT);
    

    Good

    
    boolean isWithinSizeLimit = length < MAX_LENGTH;
    boolean isSameSize = previousSize != length;
    boolean isValidCode = isWithinSizeLimit || isSameSize;
    
    boolean isUrgent = typeCode == URGENT;
    
    return isValidCode && isUrgent;
    

    Example:

    Bad

    return ((length < MAX_LENGTH) or (previous_size != length)) and (type_code == URGENT)
    

    Good

    is_within_size_limit = length < MAX_LENGTH
    is_same_size = previous_size != length
    is_valid_code = is_within_size_limit or is_same_size
    
    is_urgent = type_code == URGENT
    
    return is_valid_code and is_urgent
    

    The competent programmer is fully aware of the strictly limited size of his own skull; therefore he approaches the programming task in full humility, and among other things he avoids clever tricks like the plague. -- Edsger Dijkstra

    [W4.2e] Implementation → Code Quality → Readability → Basic → Avoid Magic Numbers

    Can improve code quality using technique: avoid magic numbers

    When the code has a number that does not explain the meaning of the number, we call that a magic number (as in “the number appears as if by magic”). Using a named constant makes the code easier to understand because the name tells us more about the meaning of the number.

    Example:

         

    Bad

    return 3.14236;
    ...
    return 9;
    

      

    Good

    static final double PI = 3.14236;
    static final int MAX_SIZE = 10;
    ...
    return PI;
    ...
    return MAX_SIZE-1;
    

    Note: Python does not have a way to make a variable a constant. However, you can use a normal variable with an ALL_CAPS name to simulate a constant.

         

    Bad

    return 3.14236
    ...
    return 9
    

      

    Good

    PI = 3.14236
    MAX_SIZE = 10
    ...
    return PI
    ...
    return MAX_SIZE-1
    

    Similarly, we can have ‘magic’ values of other data types.

    Bad

    "Error 1432"  // A magic string!
    
    [W4.2f] Implementation → Code Quality → Readability → Basic → Make the Code Obvious

    Can improve code quality using technique: make the code obvious

    Make the code as explicit as possible, even if the language syntax allows them to be implicit. Here are some examples:

    • [Java] Use explicit type conversion instead of implicit type conversion.
    • [Java, Python] Use parentheses/braces to show grouping even when they can be skipped.
    • [Java, Python] Use enumerations when a certain variable can take only a small number of finite values. For example, instead of declaring the variable 'state' as an integer and using values 0,1,2 to denote the states 'starting', 'enabled', and 'disabled' respectively, declare 'state' as type SystemState and define an enumeration SystemState that has values 'STARTING', 'ENABLED', and 'DISABLED'.
    [W4.2g] Implementation → Code Quality → Readability → Intermediate → Structure Code Logically

    Can improve code quality using technique: structure code logically

    Lay out the code so that it adheres to the logical structure. The code should read like a story. Just like we use section breaks, chapters and paragraphs to organize a story, use classes, methods, indentation and line spacing in your code to group related segments of the code. For example, you can use blank lines to group related statements together. Sometimes, the correctness of your code does not depend on the order in which you perform certain intermediary steps. Nevertheless, this order may affect the clarity of the story you are trying to tell. Choose the order that makes the story most readable.

    [W4.2h] Implementation → Code Quality → Readability → Intermediate → Do Not 'Trip Up' Reader

    Can improve code quality using technique: do not 'trip up' reader

    Avoid things that would make the reader go ‘huh?’, such as,

    • unused parameters in the method signature
    • similar things look different
    • different things that look similar
    • multiple statements in the same line
    • data flow anomalies such as, pre-assigning values to variables and modifying it without any use of the pre-assigned value
    [W4.2i] Implementation → Code Quality → Readability → Intermediate → Practice KISSing

    Can improve code quality using technique: practice kissing

    As the old adage goes, "keep it simple, stupid” (KISS). Do not try to write ‘clever’ code. For example, do not dismiss the brute-force yet simple solution in favor of a complicated one because of some ‘supposed benefits’ such as 'better reusability' unless you have a strong justification.

    Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. --Brian W. Kernighan

    Programs must be written for people to read, and only incidentally for machines to execute. --Abelson and Sussman

    [W4.2j] Implementation → Code Quality → Readability → Intermediate → Avoid Premature Optimizations

    Can improve code quality using technique: avoid premature optimizations

    Optimizing code prematurely has several drawbacks:

    • We may not know which parts are the real performance bottlenecks. This is especially the case when the code undergoes transformations (e.g. compiling, minifying, transpiling, etc.) before it becomes an executable. Ideally, you should use a profiler tool to identify the actual bottlenecks of the code first, and optimize only those parts.
    • Optimizing can complicate the code, affecting correctness and understandability
    • Hand-optimized code can be harder for the compiler to optimize (the simpler the code, the easier for the compiler to optimize it). In many cases a compiler can do a better job of optimizing the runtime code if you don't get in the way by trying to hand-optimize the source code.

    A popular saying in the industry is make it work, make it right, make it fast which means in most cases getting the code to perform correctly should take priority over optimizing it. If the code doesn't work correctly, it has no value on matter how fast/efficient it it.

    Premature optimization is the root of all evil in programming. --Donald Knuth

    Note that there are cases where optimizing takes priority over other things e.g. when writing code for resource-constrained environments. This guideline simply a caution that you should optimize only when it is really needed.

    [W4.2k] Implementation → Code Quality → Readability → Intermediate → SLAP Hard

    Can improve code quality using technique: SLAP hard

    Avoid varying the level of abstraction within a code fragment. Note: The Productive Programmer (by Neal Ford) calls this the SLAP principle i.e. Single Level of Abstraction Per method.

    Example:

    Bad

    readData();
    salary = basic*rise+1000;
    tax = (taxable?salary*0.07:0);
    displayResult();
    

    Good

    readData();
    processData();
    displayResult();
    
     

    Design → Design Fundamentals → Abstraction →

    What

    Abstraction is a technique for dealing with complexity. It works by establishing a level of complexity we are interested in, and suppressing the more complex details below that level.

    The guiding principle of abstraction is that only details that are relevant to the current perspective or the task at hand needs to be considered. As most programs are written to solve complex problems involving large amounts of intricate details, it is impossible to deal with all these details at the same time. That is where abstraction can help.

    Ignoring lower level data items and thinking in terms of bigger entities is called data abstraction.

    Within a certain software component, we might deal with a user data type, while ignoring the details contained in the user data item such as name, and date of birth. These details have been ‘abstracted away’ as they do not affect the task of that software component.

    Control abstraction abstracts away details of the actual control flow to focus on tasks at a simplified level.

    print(“Hello”) is an abstraction of the actual output mechanism within the computer.

    Abstraction can be applied repeatedly to obtain progressively higher levels of abstractions.

    An example of different levels of data abstraction: a File is a data item that is at a higher level than an array and an array is at a higher level than a bit.

    An example of different levels of control abstraction: execute(Game) is at a higher level than print(Char) which is at a higher than an Assembly language instruction MOV.

    Abstraction is a general concept that is not limited to just data or control abstractions.

    Some more general examples of abstraction:

    • An OOP class is an abstraction over related data and behaviors.
    • An architecture is a higher-level abstraction of the design of a software.
    • Models (e.g., UML models) are abstractions of some aspect of reality.
    [W4.2l] Implementation → Code Quality → Readability → Advanced → Make the Happy Path Prominent

    Can improve code quality using technique: make the happy path prominent

    The happy path (i.e. the execution path taken when everything goes well) should be clear and prominent in your code. Restructure the code to make the happy path unindented as much as possible. It is the ‘unusual’ cases that should be indented. Someone reading the code should not get distracted by alternative paths taken when error conditions happen. One technique that could help in this regard is the use of guard clauses.

    Example:

    Bad

    if (!isUnusualCase) {  //detecting an unusual condition
        if (!isErrorCase) {
            start();    //main path
            process();
            cleanup();
            exit();
        } else {
            handleError();
        }
    } else {
        handleUnusualCase(); //handling that unusual condition
    }
    

    In the code above,

    • Unusual condition detection is separated from their handling.
    • Main path is nested deeply.

    Good

    if (isUnusualCase) { //Guard Clause
        handleUnusualCase();
        return;
    }
    
    if (isErrorCase) { //Guard Clause
        handleError();
        return;
    }
    
    start();
    process();
    cleanup();
    exit();
    

    In contrast, the above code

    • deals with unusual conditions as soon as they are detected so that the reader doesn't have to remember them for long.
    • keeps the main path un-indented.

    Naming

    [W4.2m] Implementation → Code Quality → Naming → Introduction

    Can explain the need for good names in code

    Proper naming improves the readability. It also reduces bugs caused by ambiguities regarding the intent of a variable or a method.

    There are only two hard things in Computer Science: cache invalidation and naming things. -- Phil Karlton

    [W4.2n] Implementation → Code Quality → Naming → Basic → Use Nouns for Things and Verbs for Actions

    Can improve code quality using technique: use nouns for things and verbs for actions

    Every system is built from a domain-specific language designed by the programmers to describe that system. Functions are the verbs of that language, and classes are the nouns. ― Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship

    Use nouns for classes/variables and verbs for methods/functions.

    Examples:

    Name for a Bad Good
    Class CheckLimit LimitChecker
    method result() calculate()

    Distinguish clearly between single-valued and multivalued variables.

    Examples:

    Good

    Person student;
    ArrayList<Person> students;
    

    Good

    student = Person('Jim')
    students = [Person('Jim'), Person('Alice')]
    
    [W4.2o] Implementation → Code Quality → Naming → Basic → Use Standard Words

    Can improve code quality using technique: use standard words

    Use correct spelling in names. Avoid 'texting-style' spelling. Avoid foreign language words, slang, and names that are only meaningful within specific contexts/times e.g. terms from private jokes, a TV show currently popular in your country

    [W4.2p] Implementation → Code Quality → Naming → Intermediate → Use Name to Explain

    Can improve code quality using technique: use name to explain

    A name is not just for differentiation; it should explain the named entity to the reader accurately and at a sufficient level of detail.

    Examples:

    Bad Good
    processInput() (what 'process'?) removeWhiteSpaceFromInput()
    flag isValidInput
    temp

    If the name has multiple words, they should be in a sensible order.

    Examples:

    Bad Good
    bySizeOrder() orderBySize()

    Imagine going to the doctor's and saying "My eye1 is swollen"! Don’t use numbers or case to distinguish names.

    Examples:

    Bad Bad Good
    value1, value2 value, Value originalValue, finalValue
    [W4.2undefined] Implementation → Code Quality → Naming → Intermediate → Not Too Long, Not Too Short

    Can improve code quality using technique: not too long, not too short

    While it is preferable not to have lengthy names, names that are 'too short' are even worse. If you must abbreviate or use acronyms, do it consistently. Explain their full meaning at an obvious location.

    [W4.2undefined] Implementation → Code Quality → Naming → Intermediate → Avoid Misleading Names

    Can improve code quality using technique: avoid misleading names

    Related things should be named similarly, while unrelated things should NOT.

    Example: Consider these variables

    • colorBlack : hex value for color black
    • colorWhite : hex value for color white
    • colorBlue : number of times blue is used
    • hexForRed : : hex value for color red

    This is misleading because colorBlue is named similar to colorWhite and colorBlack but has a different purpose while hexForRed is named differently but has very similar purpose to the first two variables. The following is better:

    • hexForBlack hexForWhite hexForRed
    • blueColorCount

    Avoid misleading or ambiguous names (e.g. those with multiple meanings), similar sounding names, hard-to-pronounce ones (e.g. avoid ambiguities like "is that a lowercase L, capital I or number 1?", or "is that number 0 or letter O?"), almost similar names.

    Examples:

    Bad Good Reason
    phase0 phaseZero Is that zero or letter O?
    rwrLgtDirn rowerLegitDirection Hard to pronounce
    right left wrong rightDirection leftDirection wrongResponse right is for 'correct' or 'opposite of 'left'?
    redBooks readBooks redColorBooks booksRead red and read (past tense) sounds the same
    FiletMignon egg If the requirement is just a name of a food, egg is a much easier to type/say choice than FiletMignon

    Unsafe Practices

    [W4.2undefined] Implementation → Code Quality → Error-Prone Practices → Introduction

    Can explain the need for avoiding error-prone shortcuts

    It is safer to use language constructs in the way they are meant to be used, even if the language allows shortcuts. Some such coding practices are common sources of bugs. Know them and avoid them.

    [W4.2undefined] Implementation → Code Quality → Error-Prone Practices → Basic → Use the Default Branch

    Can improve code quality using technique: use the default branch

    Always include a default branch in case statements.

    Furthermore, use it for the intended default action and not just to execute the last option. If there is no default action, you can use the 'default' branch to detect errors (i.e. if execution reached the default branch, throw an exception). This also applies to the final else of an if-else construct. That is, the final else should mean 'everything else', and not the final option. Do not use else when an if condition can be explicitly specified, unless there is absolutely no other possibility.

    Bad

    if (red) print "red";
    else print "blue";
    

    Good

    if (red) print "red";
    else if (blue) print "blue";
    else error("incorrect input");
    
    [W4.2undefined] Implementation → Code Quality → Error-Prone Practices → Basic → Don't Recycle Variables or Parameters

    Can improve code quality using technique: don't recycle variables or parameters

    • Use one variable for one purpose. Do not reuse a variable for a different purpose other than its intended one, just because the data type is the same.
    • Do not reuse formal parameters as local variables inside the method.

    Bad

    double computeRectangleArea(double length, double width) {
        length = length * width;
        return length;
    }
    
    

    Good

    double computeRectangleArea(double length, double width) {
        double area;
        area = length * width;
        return area;
    }
    
    [W4.2undefined] Implementation → Code Quality → Error-Prone Practices → Basic → Avoid Empty Catch Blocks

    Can improve code quality using technique: avoid empty catch blocks

    Never write an empty catch statement. At least give a comment to explain why the catch block is left empty.

    [W4.2undefined] Implementation → Code Quality → Error-Prone Practices → Basic → Delete Dead Code

    Can improve code quality using technique: delete dead code

    We all feel reluctant to delete code we have painstakingly written, even if we have no use for that code any more ("I spent a lot of time writing that code; what if we need it again?"). Consider all code as baggage you have to carry; get rid of unused code the moment it becomes redundant. If you need that code again, simply recover it from the revision control tool you are using. Deleting code you wrote previously is a sign that you are improving.

    [W4.2undefined] Implementation → Code Quality → Error-Prone Practices → Intermediate → Minimise Scope of Variables

    Can improve code quality using technique: minimise scope of variables

    Minimize global variables. Global variables may be the most convenient way to pass information around, but they do create implicit links between code segments that use the global variable. Avoid them as much as possible.

    Define variables in the least possible scope. For example, if the variable is used only within the if block of the conditional statement, it should be declared inside that if block.

    The most powerful technique for minimizing the scope of a local variable is to declare it where it is first used. -- Effective Java, by Joshua Bloch

    Resources:

    [W4.2undefined] Implementation → Code Quality → Error-Prone Practices → Intermediate → Minimise Code Duplication

    Can improve code quality using technique: minimise code duplication

    Code duplication, especially when you copy-paste-modify code, often indicates a poor quality implementation. While it may not be possible to have zero duplication, always think twice before duplicating code; most often there is a better alternative.

    This guideline is closely related to the DRY Principle.

    Supplmentary → Principles →

    DRY Principle

    DRY (Don't Repeat Yourself) Principle: Every piece of knowledge must have a single, unambiguous, authoritative representation within a system The Pragmatic Programmer, by Andy Hunt and Dave Thomas

    This principle guards against duplication of information.

    The functionality implemented twice is a violation of the DRY principle even if the two implementations are different.

    The value a system-wide timeout being defined in multiple places is a violation of DRY.


    Code Comments

    [W4.2undefined] Implementation → Code Quality → Comments → Introduction

    Can explain the need for commenting minimally but sufficiently

    Good code is its own best documentation. As you’re about to add a comment, ask yourself, ‘How can I improve the code so that this comment isn’t needed?’ Improve the code and then document it to make it even clearer. --Steve McConnell, Author of Clean Code

    Some think commenting heavily increases the 'code quality'. This is not so. Avoid writing comments to explain bad code. Improve the code to make it self-explanatory.

    [W4.2undefined] Implementation → Code Quality → Comments → Basic → Do Not Repeat the Obvious

    Can improve code quality using technique: do not repeat the obvious

    If the code is self-explanatory, refrain from repeating the description in a comment just for the sake of 'good documentation'.

    Bad

    // increment x
    x++;
    
    //trim the input
    trimInput();
    
    [W4.2undefined] Implementation → Code Quality → Comments → Basic → Write to the Reader

    Can improve code quality using technique: write to the reader

    Do not write comments as if they are private notes to self. Instead, write them well enough to be understood by another programmer. One type of comments that is almost always useful is the header comment that you write for a class or an operation to explain its purpose.

    Examples:

    Bad Reason: this comment will only make sense to the person who wrote it

    // a quick trim function used to fix bug I detected overnight
    void trimInput(){
        ....
    }
    

    Good

    /** Trims the input of leading and trailing spaces */
    void trimInput(){
        ....
    }
    

    Bad Reason: this comment will only make sense to the person who wrote it

    # a quick trim function used to fix bug I detected overnight
    def trim_input():
        ...
    

    Good

    def trim_input():
    """Trim the input of leading and trailing spaces"""
        ...
    
    [W4.2undefined] Implementation → Code Quality → Comments → Intermediate → Explain WHAT and WHY, not HOW

    Can improve code quality using technique: explain what and why, not how

    Comments should explain what and why aspect of the code, rather than the how aspect.

    What : The specification of what the code supposed to do. The reader can compare such comments to the implementation to verify if the implementation is correct

    Example: This method is possibly buggy because the implementation does not seem to match the comment. In this case the comment could help the reader to detect the bug.

    /** Removes all spaces from the {@code input} */
    void compact(String input){
        input.trim();
    }
    

    Why : The rationale for the current implementation.

    Example: Without this comment, the reader will not know the reason for calling this method.

    // Remove spaces to comply with IE23.5 formatting rules
    compact(input);
    

    How : The explanation for how the code works. This should already be apparent from the code, if the code is self-explanatory. Adding comments to explain the same thing is redundant.

    Example:

    Bad Reason: Comment explains how the code works.

    // return true if both left end and right end are correct or the size has not incremented
    return (left && right) || (input.size() == size);
    

    Good Reason: Code refactored to be self-explanatory. Comment no longer needed.

    
    boolean isSameSize = (input.size() == size) ;
    return (isLeftEndCorrect && isRightEndCorrect) || isSameSize;
    

    [W4.3] Exception Handling

    [W4.3a] Implementation → Error Handling → Introduction → What :

    Can explain error handling

    Well-written applications include error-handling code that allows them to recover gracefully from unexpected errors. When an error occurs, the application may need to request user intervention, or it may be able to recover on its own. In extreme cases, the application may log the user off or shut down the system. --Microsoft

    [W4.3b] Implementation → Error Handling → Exceptions → What :

    Can explain exceptions

    Exceptions are used to deal with 'unusual' but not entirely unexpected situations that the program might encounter at run time.

    Exception:

    The term exception is shorthand for the phrase "exceptional event." An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions. –- Java Tutorial (Oracle Inc.)

    Examples:

    • A network connection encounters a timeout due to a slow server.
    • The code tries to read a file from the hard disk but the file is corrupted and cannot be read.
    [W4.3c] C++ to Java → Exceptions → What are Exceptions? :

    Can explain Java Exceptions

    Given below is an extract from the -- Java Tutorial, with some adaptations.

    There are three basic categories of exceptions In Java:

    • Checked exceptions: exceptional conditions that a well-written application should anticipate and recover from. All exceptions are checked exceptions, except for Error, RuntimeException, and their subclasses.

    Suppose an application prompts a user for an input file name, then opens the file by passing the name to the constructor for java.io.FileReader. Normally, the user provides the name of an existing, readable file, so the construction of the FileReader object succeeds, and the execution of the application proceeds normally. But sometimes the user supplies the name of a nonexistent file, and the constructor throws java.io.FileNotFoundException. A well-written program will catch this exception and notify the user of the mistake, possibly prompting for a corrected file name.

    • Errors: exceptional conditions that are external to the application, and that the application usually cannot anticipate or recover from. Errors are those exceptions indicated by Error and its subclasses.

    Suppose that an application successfully opens a file for input, but is unable to read the file because of a hardware or system malfunction. The unsuccessful read will throw java.io.IOError. An application might choose to catch this exception, in order to notify the user of the problem — but it also might make sense for the program to print a stack trace and exit.

    • Runtime exceptions: conditions that are internal to the application, and that the application usually cannot anticipate or recover from. Runtime exceptions are those indicated by RuntimeException and its subclasses. These usually indicate programming bugs, such as logic errors or improper use of an API.

    Consider the application described previously that passes a file name to the constructor for FileReader. If a logic error causes a null to be passed to the constructor, the constructor will throw NullPointerException. The application can catch this exception, but it probably makes more sense to eliminate the bug that caused the exception to occur.

    Errors and runtime exceptions are collectively known as unchecked exceptions.

    [W4.3d] Implementation → Error Handling → Exceptions → How :

    Can explain how exception handling is done typically

    Most languages allow code that encountered an "exceptional" situation to encapsulate details of the situation in an Exception object and throw/raise that object so that another piece of code can catch it and deal with it. This is especially useful when the code that encountered the unusual situation does not know how to deal with it.

    The extract below from the -- Java Tutorial (with slight adaptations) explains how exceptions are typically handled.

    When an error occurs at some point in the execution, the code being executed creates an exception object and hands it off to the runtime system. The exception object contains information about the error, including its type and the state of the program when the error occurred. Creating an exception object and handing it to the runtime system is called throwing an exception.

    After a method throws an exception, the runtime system attempts to find something to handle it in the call stack. The runtime system searches the call stack for a method that contains a block of code that can handle the exception. This block of code is called an exception handler. The search begins with the method in which the error occurred and proceeds through the call stack in the reverse order in which the methods were called. When an appropriate handler is found, the runtime system passes the exception to the handler. An exception handler is considered appropriate if the type of the exception object thrown matches the type that can be handled by the handler.

    The exception handler chosen is said to catch the exception. If the runtime system exhaustively searches all the methods on the call stack without finding an appropriate exception handler, the program terminates.

    Advantages of exception handling in this way:

    • The ability to propagate error information through the call stack.
    • The separation of code that deals with 'unusual' situations from the code that does the 'usual' work.

    Which are benefits of exceptions?

    • a. Exceptions allow us to separate normal code from error handling code.
    • b. Exceptions can prevent problems that happen in the environment.
    • c. Exceptions allow us to handle in one location an error raised in another location.

    (a) (c)

    Explanation: Exceptions cannot prevent problems in the environment. They can only be used to handle and recover from such problems.

    [W4.3e] C++ to Java → Exceptions → How to Use Exceptions :

    Can use Java Exceptions

    The content below uses extracts from the -- Java Tutorial, with some adaptations.

    A program can catch exceptions by using a combination of the try, catch blocks.

    • The try block identifies a block of code in which an exception can occur.
    • The catch block identifies a block of code, known as an exception handler, that can handle a particular type of exception.

    The writeList() method below calls a method process() that can cause two type of exceptions. It uses a try-catch construct to deal with each exception.

    public void writeList() {
        print("starting method");
        try {
            print("starting process");
            process();
            print("finishing process");
    
        } catch (IndexOutOfBoundsException e) {
            print("caught IOOBE");
    
        } catch (IOException e) {
            print("caught IOE");
    
        }
        print("finishing method");
    }
    

    Some possible outputs:

    No exceptions IOException IndexOutOfBoundsException
    starting method
    starting process
    finishing process
    finishing method
    starting method
    starting process
    finishing process
    caught IOE
    finishing method
    starting method
    starting process
    finishing process
    caught IOOBE
    finishing method

    You can use a finally block to specify code that is guaranteed to execute with or without the exception. This is the right place to close files, recover resources, and otherwise clean up after the code enclosed in the try block.

    The writeList() method below has a finally block:

    public void writeList() {
        print("starting method");
        try {
            print("starting process");
            process();
            print("finishing process");
    
        } catch (IndexOutOfBoundsException e) {
            print("caught IOOBE");
    
        } catch (IOException e) {
            print("caught IOE");
    
        } finally {
            // clean up
            print("cleaning up");
        }
        print("finishing method");
    }
    

    Some possible outputs:

    No exceptions IOException IndexOutOfBoundsException
    starting method
    starting process
    finishing process
    cleaning up
    finishing method
    starting method
    starting process
    finishing process
    caught IOE
    cleaning up
    finishing method
    starting method
    starting process
    finishing process
    caught IOOBE
    cleaning up
    finishing method
    • The try statement should contain at least one catch block or a finally block and may have multiple catch blocks.

    • The class of the exception object indicates the type of exception thrown. The exception object can contain further information about the error, including an error message.

    You can use the throw statement to throw an exception. The throw statement requires a throwable object as the argument.

    Here's an example of a throw statement.

    if (size == 0) {
        throw new EmptyStackException();
    }
    

    In Java, Checked exceptions are subject to the Catch or Specify Requirement: code that might throw checked exceptions must be enclosed by either of the following:

    • A try statement that catches the exception. The try must provide a handler for the exception.
    • A method that specifies that it can throw the exception. The method must provide a throws clause that lists the exception.

    Unchecked exceptions are not required to follow to the Catch or Specify Requirement but you can apply the requirement to them too.

    Here's an example of a method specifying that it throws certain checked exceptions:

    public void writeList() throws IOException, IndexOutOfBoundsException {
        print("starting method");
        process();
        print("finishing method");
    }
    
    Some possible outputs:
    
    No exceptions IOException IndexOutOfBoundsException
    starting method
    finishing method
    starting method
    finishing method
    starting method
    finishing method

    Java comes with a collection of built-in exception classes that you can use. When they are not enough, it is possible to create your own exception classes.

    The Main class below parses a string descriptor of a rectangle of the format "WIDTHxHEIGHT" e.g., "3x4" and prints the area of the rectangle.

    public class Main {
    
        public static void printArea(String descriptor){
            //TODO: modify the code below
            System.out.println(descriptor + "=" + calculateArea(descriptor));
        }
    
        private static int calculateArea(String descriptor) {
            //TODO: modify the code below
            String[] dimensions = descriptor.split("x");
            return Integer.parseInt(dimensions[0]) * Integer.parseInt(dimensions[1]);
        }
    
        public static void main(String[] args) {
            printArea("3x4");
            printArea("5x5");
        }
    }
    

    3x4=12
    5x5=25
    
    1. Update the code of printArea to print an error message if WIDTH and/or HEIGHT are not numbers e.g., "Ax4"
      💡 calculateArea will throw the unchecked exception NumberFormatException if the code tries to parse a non-number to an integer.

    2. Update the code of printArea to print an error message if the descriptor is missing WIDTH and/or HEIGHT e.g., "x4"
      💡 calculateArea will throw the unchecked exception IndexOutOfBoundsException if one or both dimensions are missing.

    3. Update the code of calculateArea to throw the checked exception IllegalShapeException if there are more than 2 dimensions e.g., "5x4x3" and update the printArea to print an error message for those cases. Here is the code for the IllegalShapeException.java

    public class IllegalShapeException extends Exception {
      //no other code needed
    }
    

    Here is the expected behavior after you have done the above changes:

    public class Main {
    
        //...
    
        public static void main(String[] args) {
            printArea("3x4");
            printArea("3xy");
            printArea("3x");
            printArea("3");
            printArea("3x4x5");
        }
    }
    

    3x4=12
    WIDTH or HEIGHT is not a number: 3xy
    WIDTH or HEIGHT is missing: 3x
    WIDTH or HEIGHT is missing: 3
    Too many dimensions: 3x4x5
    
    public class Main {
    
        public static void printArea(String descriptor){
            try {
                System.out.println(descriptor + "=" + calculateArea(descriptor));
            } catch (NumberFormatException e) {
                System.out.println("WIDTH or HEIGHT is not a number: " + descriptor);
            } // add more catch blocks here
        }
    
        private static int calculateArea(String descriptor) throws IllegalShapeException {
            String[] dimensions = descriptor.split("x");
    
            //throw IllegalShapeException here if dimensions.length > 2
    
            return Integer.parseInt(dimensions[0]) * Integer.parseInt(dimensions[1]);
        }
    
    
    }
    

    This exercise continues from the TaskManager Level 1-2 exercises quoted above.

    Enhance the TaskManager to print an error message if a command is missing parts. Use exceptions so that error detection and printing of error message happen at different places of code and the error information is passed between the two places using an Exception object.

    Here is an example output:

    Welcome to TaskManager-Level3!
    Your task? todo
    Error: Empty description for TODO
    Your task? todo read book
    Tasks in the list: 1
    Your task? print
    Tasks:
    [1] description: read book
    is done? No
    Your task?

    Suggested approach:

    • Create a TaskManagerException class that inherits the Exception class. Override the constructor that takes a String parameter so that you can specify the error information when you create a TaskManagerException object.
    • Throw a new TaskManagerException object when you detect some necessary information is missing in the command.
    • Catch that exception somewhere else and print the message inside the exception object.
    public class TaskManagerException extends Exception{
        public TaskManagerException(String message) {
            super(message);
        }
    }
    
        public static void main(String[] args) {
            // ...
            while (!isExit) {
                try {
                    line = getInput();
                    String command = line.split(" ")[0];
                    switch (command) {
                        case "todo":
                            addTodo(line);
                            break;
                        // ...
                    }
                } catch (TaskManagerException e) {
                    printError(e.getMessage());
                }
            }
            // ...
    
        }
    
        private static void addTodo(String line) throws TaskManagerException {
            String description = line.substring("todo".length()).trim();
            if (description.isEmpty()){
                throw new TaskManagerException("Empty description for TODO");
            }
            // ...
        }
    
    [W4.3f] Implementation → Error Handling → Exceptions → When :

    Can avoid using exceptions to control normal workflow

    In general, use exceptions only for 'unusual' conditions. Use normal return statements to pass control to the caller for conditions that are 'normal'.

    [W4.4] OOP: Classes & Objects

    [W4.4a] Paradigms → Object Oriented Programming → Introduction → What :

    Can describe OOP at a higher level

    Object-Oriented Programming (OOP) is a programming paradigm. A programming paradigm guides programmers to analyze programming problems, and structure programming solutions, in a specific way.

    Programming languages have traditionally divided the world into two parts—data and operations on data. Data is static and immutable, except as the operations may change it. The procedures and functions that operate on data have no lasting state of their own; they’re useful only in their ability to affect data.

    This division is, of course, grounded in the way computers work, so it’s not one that you can easily ignore or push aside. Like the equally pervasive distinctions between matter and energy and between nouns and verbs, it forms the background against which we work. At some point, all programmers—even object-oriented programmers—must lay out the data structures that their programs will use and define the functions that will act on the data.

    With a procedural programming language like C, that’s about all there is to it. The language may offer various kinds of support for organizing data and functions, but it won’t divide the world any differently. Functions and data structures are the basic elements of design.

    Object-oriented programming doesn’t so much dispute this view of the world as restructure it at a higher level. It groups operations and data into modular units called objects and lets you combine objects into structured networks to form a complete program. In an object-oriented programming language, objects and object interactions are the basic elements of design.

    -- Object-Oriented Programming with Objective-C, Apple

    Some other examples of programming paradigms are:

    Paradigm Programming Languages
    Procedural Programming paradigm C
    Functional Programming paradigm F#, Haskel, Scala
    Logic Programming paradigm Prolog

    Some programming languages support multiple paradigms.

    Java is primarily an OOP language but it supports limited forms of functional programming and it can be used to (although not recommended) write procedural code.  e.g. se-edu/addressbook-level1

    JavaScript and Python support functional, procedural, and OOP programming.

    A) Choose the correct statements

    • a. OO is a programming paradigm
    • b. OO guides us in how to structure the solution
    • c. OO is mainly an abstraction mechanism
    • d. OO is a programming language
    • e. OO is modeled after how the objects in real world work

    B) Choose the correct statements

    • a. Java and C++ are OO languages
    • b. C language follows the Functional Programming paradigm
    • c. Java can be used to write procedural code
    • d. Prolog follows the Logic Programming paradigm

    A) (a)(b)(c)(e)

    Explanation: While many languages support the OO paradigm, OO is not a language itself.

    B) Choose the correct statement

    (a)(b)(c)(d)

    Explanation: C follows the procedural paradigm. Yes, we can write procedural code using OO languages e.g., AddressBook-level1.

    OO is a higher level mechanism than the procedural paradigm.

    True.

    Explanation: Procedural languages work at simple data structures (e.g., integers, arrays) and functions level. Because an object is an abstraction over data+related functions, OO works at a higher level.

    [W4.4b] Paradigms → Object Oriented Programming → Objects → What :

    Can describe how OOP relates to the real world

    Every object has both state (data) and behavior (operations on data). In that, they’re not much different from ordinary physical objects. It’s easy to see how a mechanical device, such as a pocket watch or a piano, embodies both state and behavior. But almost anything that’s designed to do a job does, too. Even simple things with no moving parts such as an ordinary bottle combine state (how full the bottle is, whether or not it’s open, how warm its contents are) with behavior (the ability to dispense its contents at various flow rates, to be opened or closed, to withstand high or low temperatures).

    It’s this resemblance to real things that gives objects much of their power and appeal. They can not only model components of real systems, but equally as well fulfill assigned roles as components in software systems.

    -- Object-Oriented Programming with Objective-C, Apple

    Object Oriented Programming (OOP) views the world as a network of interacting objects.

    A real world scenario viewed as a network of interacting objects:

    You are asked to find out the average age of a group of people Adam, Beth, Charlie, and Daisy. You take a piece of paper and pen, go to each person, ask for their age, and note it down. After collecting the age of all four, you enter it into a calculator to find the total. And then, use the same calculator to divide the total by four, to get the average age. This can be viewed as the objects You, Pen, Paper, Calculator, Adam, Beth, Charlie, and Daisy interacting to accomplish the end result of calculating the average age of the four persons. These objects can be considered as connected in a certain network of certain structure.

    OOP solutions try to create a similar object network inside the computer’s memory – a sort of a virtual simulation of the corresponding real world scenario – so that a similar result can be achieved programmatically.

    OOP does not demand that the virtual world object network follow the real world exactly.

    Our previous example can be tweaked a bit as follows:

    • Use an object called Main to represent your role in the scenario.
    • As there is no physical writing involved, we can replace the Pen and Paper with an object called AgeList that is able to keep a list of ages.

    Every object has both state (data) and behavior (operations on data).

    Object Real World? Virtual World? Example of State (i.e. Data) Examples of Behavior (i.e. Operations)
    Adam Name, Date of Birth Calculate age based on birthday
    Pen - Ink color, Amount of ink remaining Write
    AgeList - Recorded ages Give the number of entries, Accept an entry to record
    Calculator Numbers already entered Calculate the sum, divide
    You/Main Average age, Sum of ages Use other objects to calculate

    Every object has an interface and an implementation.

    Every real world object has:

    • an interface that other objects can interact with
    • an implementation that supports the interface but may not be accessible to the other object

    The interface and implementation of some real-world objects in our example:

    • Calculator: the buttons and the display are part of the interface; circuits are part of the implementation.
    • Adam: In the context of our 'calculate average age' example, the interface of Adam consists of requests that adam will respond to, e.g. "Give age to the nearest year, as at Jan 1st of this year" "State your name"; the implementation includes the mental calculation Adam uses to calculate the age which is not visible to other objects.

    Similarly, every object in the virtual world has an interface and an implementation.

    The interface and implementation of some virtual-world objects in our example:

    • Adam: the interface might have a method getAge(Date asAt); the implementation of that method is not visible to other objects.

    Objects interact by sending messages.

    Both real world and virtual world object interactions can be viewed as objects sending message to each other. The message can result in the sender object receiving a response and/or the receiving object’s state being changed. Furthermore, the result can vary based on which object received the message, even if the message is identical (see rows 1 and 2 in the example below).

    Examples:

    World Sender Receiver Message Response State Change
    Real You Adam "What is your name?" "Adam" -
    Real as above Beth as above "Beth" -
    Real You Pen Put nib on paper and apply pressure Makes a mark on your paper Ink level goes down
    Virtual Main Calculator (current total is 50) add(int i): int i = 23 73 total = total + 23

    Consider the following real-world scenario.

    Tom read a Software Engineering textbook (he has been assigned to read the book) and highlighted some of the text in it.  

    Explain the following statements about OOP using the above scenario as an example.

    1. Object Oriented Programming (OOP) views the world as a network of interacting objects.
    2. Every object has both state (data) and behavior (operations on data).
    3. Every object has an interface and an implementation.
    4. Objects interact by sending messages.
    5. OOP does not demand that the virtual world object network follow the real world exactly.

    [1] Object Oriented Programming (OOP) views the world as a network of interacting objects.

    Interacting objects in the scenario: Tom, SE Textbook (Book for short), Text, (possibly) Highlighter

    💡 objects usually match nouns in the description

    [2]Every object has both state (data) and behavior (operations on data).

    Object Examples of state Examples of behavior
    Tom memory of the text read read
    Book title show text
    Text font size get highlighted

    [3] Every object has an interface and an implementation.

    • Interface of an object consists of how other objects interact with it i.e., what other objects can do to that object
    • Implementation consist of internals of the object that facilitate the interactions but not visible to other objects.
    Object Examples of interface Examples of implementation
    Tom receive reading assignment understand/memorize the text read, remember the reading assignment
    Book show text, turn page how pages are bound to the spine
    Text read how characters/words are connected together or fixed to the book

    [4] Objects interact by sending messages.

    Examples:

    • Tom sends message turn page to the Book
    • Tom sends message show text to the Book. When the Book shows the Text, Tom sends the message read to the Text which returns the text content to Tom.
    • Tom sends message highlight to the Highlighter while specifying which Text to highlight. Then the Highlighter sends the message highlight to the specified Text.

    [5] OOP does not demand that the virtual world object network follow the real world exactly.

    Examples:

    • A virtual world simulation of the above scenario can omit the Highlighter object. Instead, we can teach Text to highlight themselves when requested.
    [W4.4c] Paradigms → Object Oriented Programming → Classes → Basic :

    Can explain the relationship between classes and objects

    Writing an OOP program is essentially writing instructions that the computer uses to,

    1. create the virtual world of object network, and
    2. provide it the inputs to produce the outcome we want.

    A class contains instructions for creating a specific kind of objects. It turns out sometimes multiple objects have the same behavior because they are of the same kind. Instructions for creating a one kind (or ‘class’) of objects can be done once and that same instructions can be used to instantiate objects of that kind. We call such instructions a Class.

    Classes and objects in an example scenario

    Consider the example of writing an OOP program to calculate the average age of Adam, Beth, Charlie, and Daisy.

    Instructions for creating objects Adam, Beth, Charlie, and Daisy will be very similar because they are all of the same kind : they all represent ‘persons’ with the same interface, the same kind of data (i.e. name, DoB, etc.), and the same kind of behavior (i.e. getAge(Date), getName(), etc.). Therefore, we can have a class called Person containing instructions on how to create Person objects and use that class to instantiate objects Adam, Beth, Charlie, and Daisy.

    Similarly, we need classes AgeList, Calculator, and Main classes to instantiate one each of AgeList, Calculator, and Main objects.

    Class Objects
    Person objects representing Adam, Beth, Charlie, Daisy
    AgeList an object to represent the age list
    Calculator an object to do the calculations
    Main an object to represent you who manages the whole operation

    Consider the following scenario. If you were to simulate this in an OOP program, what are the classes and the objects you would use?

      A customer (name: John) gave a cheque to the Cashier (name: Peter) to pay for the LoTR and GoT books he bought.
    Class Objects
    Customer john
    Book LoTR, GoT
    Cheque checqueJohnGave
    Cashier peter

    Assume you are writing a CLI program called CityConnect for storing and querying distances between cities. The behavior is as follows:

    Welcome to CityConnect!
    
    Enter command: addroute Clementi BuonaVista 12
    Route from Clementi to BuonaVista with distance 12km added
    
    Enter command: getdistance Clementi BuonaVista
    Distance from Clementi to BuonaVista is 12
    
    Enter command: getdistance Clementi JurongWest
    No route exists from Clementi to JurongWest!
    
    Enter command: addroute Clementi JurongWest 24
    Route from Clementi to JurongWest with distance 24km added
    
    Enter command: getdistance Clementi JurongWest
    Distance from Clementi to JurongWest is 24
    
    Enter command: exit
    
    

    What classes would you have in your code if you write your program based on the OOP paradigm?

    One class you can have is Route

    [W4.4d] Paradigms → Object Oriented Programming → Objects → Objects as Abstractions :

    Can explain the abstraction aspect of OOP

    The concept of Objects in OOP is an abstraction mechanism because it allows us to abstract away the lower level details and work with bigger granularity entities i.e. ignore details of data formats and the method implementation details and work at the level of objects.

     

    Abstraction is a technique for dealing with complexity. It works by establishing a level of complexity we are interested in, and suppressing the more complex details below that level.

    We can deal with a Person object that represents the person Adam and query the object for Adam's age instead of dealing with details such as Adam’s date of birth (DoB), in what format the DoB is stored, the algorithm used to calculate the age from the DoB, etc.

    [W4.4e] Paradigms → Object Oriented Programming → Objects → Encapsulation Of Objects :

    Can explain the encapsulation aspect of OOP

    Encapsulation protects an implementation from unintended actions and from inadvertent access.
    -- Object-Oriented Programming with Objective-C, Apple

    An object is an encapsulation of some data and related behavior in two aspects:

    1. The packaging aspect: An object packages data and related behavior together into one self-contained unit.

    2. The information hiding aspect: The data in an object is hidden from the outside world and are only accessible using the object's interface.

    Choose the correct statements

    • a. An object is an encapsulation because it packages data and behavior into one bundle.
    • b. An object is an encapsulation because it lets us think in terms of higher level concepts such as Students rather than student-related functions and data separately.

    Don't confuse encapsulation with abstraction.

    Choose the correct statement

    (a)

    Explanation: The second statement should be: An object is an abstraction encapsulation because it lets ...

    [W4.4f] C++ to Java → Classes → Defining Classes :

    Can define Java classes

    As you know,

    • Defining a class creates a new object type with the same name.
    • Every object belongs to some object type; that is, it is an instance of some class.
    • A class definition is like a template for objects: it specifies what attributes the objects have and what methods can operate on them.
    • The new operator instantiates objects, that is, it creates new instances of a class.
    • The methods that operate on an object type are defined in the class for that object.

    Here's a class called Time, intended to represent a moment in time. It has three attributes and no methods.

    public class Time {
        private int hour;
        private int minute;
        private int second;
    }
    

    You can give a class any name you like. The Java convention is to use PascalCase format for class names.

    The code should be in a file whose name matches the class e.g., the Time class should be in a file named Time.java.

    When a class is public (e.g., the Time class in the above example) it can be used in other classes. But the instance variables that are private (e.g., the hour, minute and second attributes of the Time class) can only be accessed from inside the Time class.

    Constructos

    The syntax for constructors is similar to that of other methods, except:

    • The name of the constructor is the same as the name of the class.
    • The keyword static is omitted.
    • Do not return anything. A constructor returns the created object by default.

    When you invoke new, Java creates the object and calls your constructor to initialize the instance variables. When the constructor is done, new returns a reference to the new object.

    Here is an example constructor for the Time class:

    public Time() {
        hour = 0;
        minute = 0;
        second = 0;
    }
    

    This constructor does not take any arguments. Each line initializes an instance variable to zero (which in this example means midnight). Now you can create Time objects.

    Time time = new Time();

    Like other methods, constructors can be overloaded, which means you can provide multiple constructors with different parameters.

    You can add another constructor to the Time class to allow creating Time objects that are initialized to a specific time:

    public Time(int h, int m, int s) {
        hour = h;
        minute = m;
        second = s;
    }
    

    Here's how you can invoke the new constructor:

    Time justBeforeMidnight = new Time(11, 59, 59);
    
    this keyword

    The this keyword is a reference variable in Java that refers to the current object. You can use this the same way you use the name of any other object. For example, you can read and write the instance variables of this, and you can pass this as an argument to other methods. But you do not declare this, and you can’t make an assignment to it.

    In the following version of the constructor, the names and types of the parameters are the same as the instance variables (parameters don’t have to use the same names, but that’s a common style). As a result, the parameters shadow (or hide) the instance variables, so the keyword this is necessary to tell them apart.

    public Time(int hour, int minute, int second) {
        this.hour = hour;
        this.minute = minute;
        this.second = second;
    }
    

    this can be used to refer to a constructor of a class within the same class too.

    In this example the constructor Time() uses the this keyword to call its own overloaded constructor Time(int, int, int)

    public Time() {
        this(0, 0, 0); // call the overloaded constructor
    }
    
    public Time(int hour, int minute, int second) {
        // ...
    }
    
    
    Instance methods

    You can add methods to a class which can then be used from the objects of that class. These instance methods do not have the static keyword in the method signature. Instance methods can access attributes of the class.

    Here's how you can add a method to the Time class to get the number of seconds passed till midnight.

    public int secondsSinceMidnight() {
        return hour*60*60 + minute*60 + second;
    }
    

    Here's how you can use that method.

    Time t = new Time(0, 2, 5);
    System.out.println(t.secondsSinceMidnight() + " seconds since midnight!");
    

    Define a Circle class so that the code given below produces the given output. The nature of the class is a follows:

    • Attributes(all private):
      • int x, int y: represents the location of the circle
      • double radius: the radius of the circle
    • Constructors:
      • Circle(): initializes x, y, radius to 0
      • Circle(int x, int y, double radius): initializes the attributes to the given values
    • Methods:
      • getArea(): int
        Returns the area of the circle as an int value (not double). Calculated as 2xPIx(radius)2
        💡 You can convert to double to an int using (int) e.g., x = (int)2.25 gives x the value 2.
        💡 You can use Math.PI to get the value of Pi
        💡 You can use Math.pow() to raise a number to a specific power e.g., Math.pow(3, 2) calculates 32
    public class Main {
        public static void main(String[] args) {
            Circle c = new Circle();
    
            System.out.println(c.getArea());
            c = new Circle(1, 2, 5);
            System.out.println(c.getArea());
    
        }
    }
    

    0
    78
    
    • Put the Circle class in a file called Circle.java

    Partial solution:

    public class Circle {
        private int x;
        // ...
    
        public Circle(){
            this(0, 0, 0);
        }
    
        public Circle(int x, int y, double radius){
            this.x = x;
            // ...
        }
    
        public int getArea(){
            double area = Math.PI * Math.pow(radius, 2);
            return (int)area;
        }
    
    }
    
    [W4.4g] C++ to Java → Classes → Getters and setters :

    Can define getters and setters

    As the instance variables of Time are private, you can access them from within the Time class only. To compensate, you can provide methods to access attributes:

    public int getHour() {
        return hour;
    }
    
    public int getMinute() {
        return minute;
    }
    
    public int getSecond() {
        return second;
    }
    

    Methods like these are formally called “accessors”, but more commonly referred to as getters. By convention, the method that gets a variable named something is called getSomething.

    Similarly, you can provide setter methods to modify attributes of a Time object:

    public void setHour(int hour) {
        this.hour = hour;
    }
    
    public void setMinute(int minute) {
        this.minute = minute;
    }
    
    public void setSecond(int second) {
        this.second = second;
    }
    

    Consider the Circle class below:

    public class Circle {
        private int x;
        private int y;
        private double radius;
    
        public Circle(){
            this(0, 0, 0);
        }
    
        public Circle(int x, int y, double radius){
            this.x = x;
            this.y = y;
            this.radius = radius;
        }
    
        public int getArea(){
            double area = Math.PI * Math.pow(radius, 2);
            return (int)area;
        }
    
    }
    

    Update it as follows so that code given below produces the given output.

    • Add getter/setter methods for all three attributes
    • Update the setters and constructors such that if the radius supplied is negative, the code automatically set the radius to 0 instead.
    public class Main {
        public static void main(String[] args) {
            Circle c = new Circle(1,2, 5);
    
            c.setX(4);
            c.setY(5);
            c.setRadius(6);
            System.out.println("x      : " + c.getX());
            System.out.println("y      : " + c.getY());
            System.out.println("radius : " + c.getRadius());
            System.out.println("area   : " + c.getArea());
    
            c.setRadius(-5);
            System.out.println("radius : " + c.getRadius());
            c = new Circle(1, 1, -4);
            System.out.println("radius : " + c.getRadius());
    
        }
    }
    

    x      : 4
    y      : 5
    radius : 6.0
    area   : 113
    radius : 0.0
    radius : 0.0
    

    Partial solution:

    public Circle(int x, int y, double radius){
        setX(x);
        setY(y);
        setRadius(radius);
    }
    
    public void setRadius(double radius) {
        this.radius = Math.max(radius, 0);
    }
    
    [W4.4h] Paradigms → Object Oriented Programming → Classes → Class-Level Members :

    Can explain class-level members

    While all objects of a class has the same attributes, each object has its own copy of the attribute value.

    All Person objects have the Name attribute but the value of that attribute varies between Person objects.

    However, some attributes are not suitable to be maintained by individual objects. Instead, they should be maintained centrally, shared by all objects of the class. They are like ‘global variables’ but attached to a specific class. Such variables whose value is shared by all instances of a class are called class-level attributes.

    The attribute totalPersons should be maintained centrally and shared by all Person objects rather than copied at each Person object.

    Similarly, when a normal method is being called, a message is being sent to the receiving object and the result may depend on the receiving object.

    Sending the getName() message to Adam object results in the response "Adam" while sending the same message to the Beth object gets the response "Beth".

    However, there can be methods related to a specific class but not suitable for sending message to a specific object of that class. Such methods that are called using the class instead of a specific instance are called class-level methods.

    The method getTotalPersons() is not suitable to send to a specific Person object because a specific object of the Person class should not know about the total number of Person objects.

    Class-level attributes and methods are collectively called class-level members (also called static members sometimes because some programming languages use the keyword static to identify class-level members). They are to be accessed using the class name rather than an instance of the class.

    Which of these are suitable as class-level variables?

    • a. system: multi-player Pac Man game, Class: Player, variable: totalScore
    • b. system: eLearning system, class: Course, variable: totalStudents
    • c. system: ToDo manager, class: Task, variable: totalPendingTasks
    • d. system: any, class: ArrayList, variable: total (i.e., total items in a given ArrayList object)

    (c)

    Explanation: totalPendingTasks should not be managed by individual Task objects and therefore suitable to be maintained as a class-level variable. The other variables should be managed at instance level as their value varies from instance to instance. e.g., totalStudents for one Course object will differ from totalStudents of another.

    [W4.4i] C++ to Java → Classes → Class-Level Members :

    Can use class-level members

    The content below is an extract from -- Java Tutorial, with slight adaptations.

    When a number of objects are created from the same class blueprint, they each have their own distinct copies of instance variables. In the case of a Bicycle class, the instance variables are gear, and speed. Each Bicycle object has its own values for these variables, stored in different memory locations.

    Sometimes, you want to have variables that are common to all objects. This is accomplished with the static modifier. Fields that have the static modifier in their declaration are called static fields or class variables. They are associated with the class, rather than with any object. Every instance of the class shares a class variable, which is in one fixed location in memory. Any object can change the value of a class variable, but class variables can also be manipulated without creating an instance of the class.

    Suppose you want to create a number of Bicycle objects and assign each a serial number, beginning with 1 for the first object. This ID number is unique to each object and is therefore an instance variable. At the same time, you need a field to keep track of how many Bicycle objects have been created so that you know what ID to assign to the next one. Such a field is not related to any individual object, but to the class as a whole. For this you need a class variable, numberOfBicycles, as follows:

    public class Bicycle {
    
        private int gear;
        private int speed;
    
        // an instance variable for the object ID
        private int id;
    
        // a class variable for the number of Bicycle objects instantiated
        private static int numberOfBicycles = 0;
            ...
    }
    

    Class variables are referenced by the class name itself, as in Bicycle.numberOfBicycles This makes it clear that they are class variables.

    The Java programming language supports static methods as well as static variables. Static methods, which have the static modifier in their declarations, should be invoked with the class name, without the need for creating an instance of the class, as in ClassName.methodName(args)

    The static modifier, in combination with the final modifier, is also used to define constants. The final modifier indicates that the value of this field cannot change.For example, the following variable declaration defines a constant named PI, whose value is an approximation of pi (the ratio of the circumference of a circle to its diameter): static final double PI = 3.141592653589793;

    Here is an example with class-level variables and class-level methods:

    public class Bicycle {
    
        private int gear;
        private int speed;
    
        private int id;
    
        private static int numberOfBicycles = 0;
    
    
        public Bicycle(int startSpeed, int startGear) {
            gear = startGear;
            speed = startSpeed;
    
            numberOfBicycles++;
            id = numberOfBicycles;
        }
    
        public int getID() {
            return id;
        }
    
        public static int getNumberOfBicycles() {
            return numberOfBicycles;
        }
    
        public int getGear(){
            return gear;
        }
    
        public void setGear(int newValue) {
            gear = newValue;
        }
    
        public int getSpeed() {
            return speed;
        }
    
        // ...
    
    }
    

    💡 Explanation of System.out.println(...):

    • out is a class-level public attribute of the System class.
    • println is a instance level method of the out object.

    Consider the Circle class below:

    public class Circle {
        private int x;
        private int y;
        private double radius;
    
        public Circle(){
            this(0, 0, 0);
        }
    
        public Circle(int x, int y, double radius){
            setX(x);
            setY(y);
            setRadius(radius);
        }
    
        public int getX() {
            return x;
        }
    
        public void setX(int x) {
            this.x = x;
        }
    
        public int getY() {
            return y;
        }
    
        public void setY(int y) {
            this.y = y;
        }
    
        public double getRadius() {
            return radius;
        }
    
        public void setRadius(double radius) {
            this.radius = Math.max(radius, 0);
        }
    
        public int getArea(){
            double area = Math.PI * Math.pow(radius, 2);
            return (int)area;
        }
    }
    

    Update it as follows so that code given below produces the given output.

    • Add a class-level getMaxRadius method that returns the maximum radius that has been used in all Circle objects created thus far.
    public class Main {
        public static void main(String[] args) {
            Circle c = new Circle();
            System.out.println("max radius used so far : " + Circle.getMaxRadius());
            c = new Circle(0, 0, 10);
            System.out.println("max radius used so far : " + Circle.getMaxRadius());
            c = new Circle(0, 0, -15);
            System.out.println("max radius used so far : " + Circle.getMaxRadius());
            c.setRadius(12);
            System.out.println("max radius used so far : " + Circle.getMaxRadius());
        }
    }
    

    max radius used so far : 0.0
    max radius used so far : 10.0
    max radius used so far : 10.0
    max radius used so far : 12.0
    

    You can use a static variable maxRadius to track the maximum value used for the radius attribute so far.

    Partial solution:

    public void setRadius(double radius) {
        this.radius = Math.max(radius, 0);
        if (maxRadius < this.radius){
            // ...
        }
    }
    
    [W4.4j] Paradigms → Object Oriented Programming → Classes → Enumerations :

    Can explain the meaning of enumerations

    An Enumeration is a fixed set of values that can be considered as a data type. An enumeration is often useful when using a regular data type such as int or String would allow invalid values to be assigned to a variable. You are recommended to enumeration types any time you need to represent a fixed set of constants.

    Suppose you want a variable to store the priority of something. There are only three priority levels: high, medium, and low. You can declare the variable as of type int and use only values 2, 1, and 0 to indication the three priority levels. However, this opens the possibility of an invalid values such as 9 to be assigned to it. But if you define an enumeration type called Priority that has three values HIGH, MEDIUM, LOW only, a variable of type Priority will never be assigned an invalid value because the compiler is able to catch such an error.

    Priority: HIGH, MEDIUM, LOW

    [W4.5] Java: enumerations

    [W4.5a] C++ to Java → Miscellaneous Topics → Enums :

    Can use Java enumerations

    You can define an enum type by using the enum keyword. Because they are constants, the names of an enum type's fields are in uppercase letters e.g., FLAG_SUCCESS.

    Defining an enumeration to represent days of a week (code to be put in the Day.java file):

    public enum Day {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
        THURSDAY, FRIDAY, SATURDAY
    }
    

    Some examples of using the Day enumeration defined above:

    Day today = Day.MONDAY;
    Day[] holidays = new Day[]{Day.SATURDAY, Day.SUNDAY};
    
    switch (today) {
    case SATURDAY:
    case SUNDAY:
        System.out.println("It's the weekend");
        break;
    default:
        System.out.println("It's a week day");
    }
    

    Note that while enumerations are usually a simple set of fixed values, Java enumerations can have behaviors too, as explained in this tutorial from -- Java Tutorial

    Define an enumeration named Priority. Add the missing describe method to the code below so that it produces the output given.

    public class Main {
    
        // Add your method here
    
        public static void main(String[] args) {
            describe("Red", Priority.HIGH);
            describe("Orange", Priority.MEDIUM);
            describe("Blue", Priority.MEDIUM);
            describe("Green", Priority.LOW);
        }
    }
    

    Red indicates high priority
    Orange indicates medium priority
    Blue indicates medium priority
    Green indicates low priority
    

    Use a switch statement to select between possible values for Priority.

        public static void describe(String color, Priority p) {
            switch (p) {
                case LOW:
                    System.out.println(color + " indicates low priority");
                    break;
                // ...
            }
        }
    

    Code for the enumeration is given below:

    public enum Priority {
        HIGH, MEDIUM, LOW
    }
    

    [W4.6] OOP: Inheritance

    [W4.6a] Paradigms → Object Oriented Programming → Inheritance → What :

    Can explain the meaning of inheritance

    The OOP concept Inheritance allows you to define a new class based on an existing class.

    For example, you can use inheritance to define an EvaluationReport class based on an existing Report class so that the EvaluationReport class does not have to duplicate code that is already implemented in the Report class. The EvaluationReport can inherit the wordCount attribute and the print() method from the base class Report.

    • Other names for Base class: Parent class, Super class
    • Other names for Derived class: Child class, Sub class, Extended class

    A superclass is said to be more general than the subclass. Conversely, a subclass is said to be more specialized than the superclass.

    Applying inheritance on a group of similar classes can result in the common parts among classes being extracted into more general classes.

    Man and Woman behaves the same way for certain things. However, the two classes cannot be simply replaced with a more general class Person because of the need to distinguish between Man and Woman for certain other things. A solution is to add the Person class as a superclass (to contain the code common to men and woment) and let Man and Woman inherit from Person class.

    Inheritance implies the derived class can be considered as a sub-type of the base class (and the base class is a super-type of the derived class), resulting in an is a relationship.

    Inheritance does not necessarily mean a sub-type relationship exists. However, the two often go hand-in-hand. For simplicity, at this point let us assume inheritance implies a sub-type relationship.

    To continue the previous example,

    • Woman is a Person
    • Man is a Person

    Inheritance relationships through a chain of classes can result in inheritance hierarchies (aka inheritance trees).

    Two inheritance hierarchies/trees are given below. Note that the triangle points to the parent class. Observe how the Parrot is a Bird as well as it is an Animal.

    Multiple Inheritance is when a class inherits directly from multiple classes. Multiple inheritance among classes is allowed in some languages (e.g., Python, C++) but not in other languages (e.g., Java, C#).

    The Honey class inherits from the Food class and the Medicine class because honey can be consumed as a food as well as a medicine (in some oriental medicine practices). Similarly, a Car is an Vehicle, an Asset and a Liability.

    Which of these are correct?

    • a. Superclass is more general than the subclass.
    • b. Child class is more specialized than the parent class.
    • c. A class can inherit behavior from its ancestor classes (ancestor classes = classes above it in the inheritance hierarchy).
    • d. Code reuse can be one benefit of inheritance.
    • e. A change to the superclass will not affect its subclasses.

    (a) (b) (c) (d)

    Explanation: (e) is incorrect. Because subclasses inherit behavior from the superclass, any changes to the superclass could affect subclasses.

    [W4.6b] Paradigms → Object Oriented Programming → Inheritance → Overloading :

    Can explain method overloading

    Method overloading is when there are multiple methods with the same name but different type signatures. Overloading is used to indicate that multiple operations do similar things but take different parameters.

    Type Signature: The type signature of an operation is the type sequence of the parameters. The return type and parameter names are not part of the type signature. However, the parameter order is significant.

    Method Type Signature
    int add(int X, int Y) (int, int)
    void add(int A, int B) (int, int)
    void m(int X, double Y) (int, double)
    void m(double X, int Y) (double, int)

    In the case below, the calculate method is overloaded because the two methods have the same name but different type signatures (String) and (int)

    • calculate(String): void
    • calculate(int): void
    [W4.6c] Paradigms → Object Oriented Programming → Inheritance → Overriding :

    Can explain method overriding

    Method overriding is when a sub-class changes the behavior inherited from the parent class by re-implementing the method. Overridden methods have the same name, same type signature, and same return type.

    Consider the following case of EvaluationReport class inheriting the Report class:

    Report methods EvaluationReport methods Overrides?
    print() print() Yes
    write(String) write(String) Yes
    read():String read(int):String No.  Reason: the two methods have different signatures; This is a case of overloading (rather than overriding).

    Paradigms → Object Oriented Programming → Inheritance →

    Overloading

    Method overloading is when there are multiple methods with the same name but different type signatures. Overloading is used to indicate that multiple operations do similar things but take different parameters.

    Type Signature: The type signature of an operation is the type sequence of the parameters. The return type and parameter names are not part of the type signature. However, the parameter order is significant.

    Method Type Signature
    int add(int X, int Y) (int, int)
    void add(int A, int B) (int, int)
    void m(int X, double Y) (int, double)
    void m(double X, int Y) (double, int)

    In the case below, the calculate method is overloaded because the two methods have the same name but different type signatures (String) and (int)

    • calculate(String): void
    • calculate(int): void

    Which of these methods override another method? A is the parent class. B inherits A.

    • a
    • b
    • c
    • d
    • e

    d

    Explanation: Method overriding requires a method in a child class to use the same method name and same parameter sequence used by one of its ancestors

    [W4.6d] C++ to Java → Inheritance → Inheritance (Basics) :

    Can use basic inheritance

    Given below is an extract from the -- Java Tutorial, with slight adaptations.

    A class that is derived from another class is called a subclass (also a derived class, extended class, or child class). The class from which the subclass is derived is called a superclass (also a base class or a parent class).

    A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.

    Every class has one and only one direct superclass (single inheritance), except the Object class, which has no superclass, . In the absence of any other explicit superclass, every class is implicitly a subclass of Object. Classes can be derived from classes that are derived from classes that are derived from classes, and so on, and ultimately derived from the topmost class, Object. Such a class is said to be descended from all the classes in the inheritance chain stretching back to Object. Java does not support multiple inheritance among classes.

    The java.lang.Object class defines and implements behavior common to all classes—including the ones that you write. In the Java platform, many classes derive directly from Object, other classes derive from some of those classes, and so on, forming a hierarchy of classes.

    The keyword extends indicates one class inheriting from another.

    Here is the sample code for a possible implementation of a Bicycle class and a MountainBike class that is a subclass of the Bicycle:

    public class Bicycle {
    
        public int gear;
        public int speed;
    
        public Bicycle(int startSpeed, int startGear) {
            gear = startGear;
            speed = startSpeed;
        }
    
        public void setGear(int newValue) {
            gear = newValue;
        }
    
        public void applyBrake(int decrement) {
            speed -= decrement;
        }
    
        public void speedUp(int increment) {
            speed += increment;
        }
    
    }
    
    public class MountainBike extends Bicycle {
    
        // the MountainBike subclass adds one field
        public int seatHeight;
    
        // the MountainBike subclass has one constructor
        public MountainBike(int startHeight, int startSpeed, int startGear) {
            super(startSpeed, startGear);
            seatHeight = startHeight;
        }
    
        // the MountainBike subclass adds one method
        public void setHeight(int newValue) {
            seatHeight = newValue;
        }
    }
    

    A subclass inherits all the fields and methods of the superclass. In the example above, MountainBike inherits all the fields and methods of Bicycle and adds the field seatHeight and a method to set it.

    Accessing Superclass Members

    If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super. You can also use super to refer to a hidden field (although hiding fields is discouraged).

    Consider this class, Superclass and a subclass, called Subclass, that overrides printMethod():

    public class Superclass {
    
        public void printMethod() {
            System.out.println("Printed in Superclass.");
        }
    }
    
    public class Subclass extends Superclass {
    
        // overrides printMethod in Superclass
        public void printMethod() {
            super.printMethod();
            System.out.println("Printed in Subclass");
        }
        public static void main(String[] args) {
            Subclass s = new Subclass();
            s.printMethod();
        }
    }
    

    Printed in Superclass.
    Printed in Subclass
    

    Within Subclass, the simple name printMethod() refers to the one declared in Subclass, which overrides the one in Superclass. So, to refer to printMethod() inherited from Superclass, Subclass must use a qualified name, using super as shown. Compiling and executing Subclass prints the following:

    Subclass Constructors

    A subclass constructor can invoke the superclass constructor. Invocation of a superclass constructor must be the first line in the subclass constructor. The syntax for calling a superclass constructor is super() (which invokes the no-argument constructor of the superclass) or super(parameter list) (to invoke the superclass constructor with a matching parameter list).

    The following example illustrates how to use the super keyword to invoke a superclass's constructor. Recall from the Bicycle example that MountainBike is a subclass of Bicycle. Here is the MountainBike (subclass) constructor that calls the superclass constructor and then adds initialization code of its own:

    public MountainBike(int startHeight, int startSpeed, int startGear) {
        super(startSpeed, startGear);
        seatHeight = startHeight;
    }
    

    Note: If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the superclass does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.

    Access Modifiers (simplified)

    Access level modifiers determine whether other classes can use a particular field or invoke a particular method. Given below is a simplified version of Java access modifiers, assuming you have not yet started placing your classes in different packages i.e., all classes are places in the root level. A full explanation of access modifiers is given in a later topic.

    There are two levels of access control:

    1. At the class level:

      • public: the class is visible to all other classes
      • no modifier: same as public

    2. At the member level:

      • public : the class is visible to all other classes
      • no modifier: same as public
      • protected: same as public
      • private: the member can only be accessed in its own class

    Background: Suppose we are creating a software to manage various tasks a person has to do. Two types of such tasks are,

    • Todos: i.e., things that needs to be done some day e.g., 'Read the book Lord of the Rings'
    • Deadlines: i.e., things to be done by a specific date/time e.g., 'Read the text book by Nov 25th'

    The Task class is given below:

    public class Task {
        protected String description;
    
        public Task(String description) {
            this.description = description;
        }
    
        public String getDescription() {
            return description;
        }
    }
    
    1. Write a Todo class that inherits from the Task class.
      • It should have an additional boolean field isDone to indicate whether the todo is done or not done.
      • It should have a isDone() method to access the isDone field and a setDone(boolean) method to set the isDone field.
    2. Write a Deadline class that inherits from the Todo class that you implemented in the previous step. It should have,
      • an additional String field by to store the details of when the task to be done e.g., Jan 25th 5pm
      • a getBy() method to access the value of the by field, and a corresponding setBy(String) method.
      • a constructor of the form Deadline(String description, String by)

    The expected behavior of the two classes is as follows:

    public class Main {
        public static void main(String[] args) {
            // create a todo task and print details
            Todo t = new Todo("Read a good book");
            System.out.println(t.getDescription());
            System.out.println(t.isDone());
    
            // change todo fields and print again
            t.setDone(true);
            System.out.println(t.isDone());
    
            // create a deadline task and print details
            Deadline d = new Deadline("Read textbook", "Nov 16");
            System.out.println(d.getDescription());
            System.out.println(d.isDone());
            System.out.println(d.getBy());
    
            // change deadline details and print again
            d.setDone(true);
            d.setBy("Postponed to Nov 18th");
            System.out.println(d.isDone());
            System.out.println(d.getBy());
        }
    }
    

    Read a good book
    false
    true
    Read textbook
    false
    Nov 16
    true
    Postponed to Nov 18th
    

    Todo class is given below. You can follow a similar approach for the Deadline class.

    public class Todo extends Task {
        protected boolean isDone;
    
        public Todo(String description) {
            super(description);
            isDone = false;
        }
    }
    

    Project Milestone: mid-v1.0

    Decide on requirements (user stories, use cases, non-functional requirements).

    💡 Given below are some guidance on the recommended progress at this point of the project (i.e., at week 4, which is the midway point of the milestone v1.0)

    This is a good time to analyze requirements with a view to conceptualizing the next version of the product (i.e. v2.0).

    • Step 1 : Brainstorm user stories

      Get together with your team members and brainstorm for user stories  for the v2.0 of the product. Note that in the module project you will deliver only up to v1.4 but here you should consider up to v2.0 (i.e. beyond the module).

      • It is ok to have more user stories than you can deliver in the project. Aim to create at least 30 user stories. Include all 'obvious' ones you can think of but also look for 'non obvious' ones that you think are likely to be missed by other teams.

      • Refer [Textbook Specifying Requirements → UserStories → Usage → (section) Tips] for tips on how to use user stories in this task.

      • You can write each user story in a piece of paper (e.g. yellow sticky note, index card, or just pieces of paper about the size of a playing card). Alternatively you can use an online tool (some examples given in [Textbook Specifying Requirements → UserStories → Usage → (panel) Tool Examples ]).

      • Note that you should not 'evaluate' the value of user stories while doing the above.  Reason: an important aspect of brainstorming is not judging the ideas generated.

     

    Requirements → Gathering Requirements →

    Brainstorming

    Brainstorming: A group activity designed to generate a large number of diverse and creative ideas for the solution of a problem.

    In a brainstorming session there are no "bad" ideas. The aim is to generate ideas; not to validate them. Brainstorming encourages you to "think outside the box" and put "crazy" ideas on the table without fear of rejection.

    What is the key characteristic about brainstorming?

    (b)

     

    Requirements → Specifying Requirements → User Stories →

    Introduction

    User story: User stories are short, simple descriptions of a feature told from the perspective of the person who desires the new capability, usually a user or customer of the system. [Mike Cohn]

    A common format for writing user stories is:

    User story format: As a {user type/role} I can {function} so that {benefit}

    Examples (from a Learning Management System):

    1. As a student, I can download files uploaded by lecturers, so that I can get my own copy of the files
    2. As a lecturer, I can create discussion forums, so that students can discuss things online
    3. As a tutor, I can print attendance sheets, so that I can take attendance during the class

    We can write user stories on index cards or sticky notes, and arrange on walls or tables, to facilitate planning and discussion. Alternatively, we can use a software (e.g., GitHub Project Boards, Trello, Google Docs, ...) to manage user stories digitally.

    [credit: https://www.flickr.com/photos/jakuza/2682466984/]

    [credit: https://www.flickr.com/photos/jakuza/with/2726048607/]

    [credit: https://commons.wikimedia.org/wiki/File:User_Story_Map_in_Action.png]

    • a. They are based on stories users tell about similar systems
    • b. They are written from the user/customer perspective
    • c. They are always written in some physical medium such as index cards or sticky notes
    • a. Reason: Despite the name, user stories are not related to 'stories' about the software.
    • b.
    • c. Reason: It is possible to use software to record user stories. When the team members are not co-located this may be the only option.

    Critique the following user story taken from a software project to build an e-commerce website.

    As a developer, I want to use Python to implement the software, so that we can resue existing Python modules.

    Refer to the definition of a user story.

    User story: User stories are short, simple descriptions of a feature told from the perspective of the person who desires the new capability, usually a user or customer of the system. [Mike Cohn]

    This user story is not written from the perspective of the user/customer.

    Bill wants you to build a Human Resource Management (HRM) system. He mentions that the system will help employees to view their own leave balance. What are the user stories you can extract from that statement?

    Remember to follow the correct format when writing user stories.

    User story format: As a {user type/role} I can {function} so that {benefit}

    As an employee, I can view my leave balance, so that I can know how many leave days I have left.

    Note: the {benefit} part may vary as it is not specifically mentioned in the question.

     
     

    You can create issues for each of the user stories and use a GitHub Project Board to sort them into categories.

    Example Project Board:

    Example Issue to represent a user story:

    A video on GitHub Project Boards:


     

    Example Google Sheet for recording user stories:


     

    Example Trello Board for recording user stories:


     

    Given their lightweight nature, user stories are quite handy for recording requirements during early stages of requirements gathering.

    💡 Here are some tips for using user stories for early stages of requirement gathering:

    • Define the target user:
      Decide your target user's profile (e.g. a student, office worker, programmer, sales person) and work patterns (e.g. Does he work in groups or alone? Does he share his computer with others?). A clear understanding of the target user will help when deciding the importance of a user story. You can even give this user a name.  e.g. Target user Jean is a university student studying in a non-IT field. She interacts with a lot of people due to her involvement in university clubs/societies. ...
    • Define the problem scope: Decide that exact problem you are going to solve for the target user.  e.g. Help Jean keep track of all her school contacts
    • Don't be too hasty to discard 'unusual' user stories:
      Those might make your product unique and stand out from the rest, at least for the target users.
    • Don't go into too much details:
      For example, consider this user story: As a user, I want to see a list of tasks that needs my attention most at the present time, so that I pay attention to them first.
      When discussing this user story, don't worry about what tasks should be considered needs my attention most at the present time. Those details can be worked out later.
    • Don't be biased by preconceived product ideas:
      When you are at the stage of identifying user needs, clear your mind of ideas you have about what your end product will look like.
    • Don't discuss implementation details or whether you are actually going to implement it:
      When gathering requirements, your decision is whether the user's need is important enough for you to want to fulfil it. Implementation details can be discussed later. If a user story turns out to be too difficult to implement later, you can always omit it from the implementation plan.

    💡 Recommended: You can use GitHub issue tracker to manage user stories, but for that you need to set up your team's GitHub organization, project fork, and issue tracker first. Instructions for doing those steps are in the panel below.

    Organization setup

    Please follow the organization/repo name format precisely because we use scripts to download your code or else our scripts will not be able to detect your work.

    After receiving your team ID, one team member should do the following steps:

    • Create a GitHub organization with the following details:
      • Organization name : CS2103-AY1819S2-TEAM_ID. e.g.  CS2103-AY1819S2-W12-1
      • Plan:  Open Source ($0/month)
    • Add members to the organization:
      • Create a team called developers to your organization.
      • Add your team members to the developers team.

    Repo setup

    Only one team member:

    1. Fork Address Book Level 4 to your team org.
    2. Rename the forked repo as main. This repo (let's call it the team repo) is to be used as the repo for your project.
    3. Ensure the issue tracker of your team repo is enabled. Reason: our bots will be posting your weekly progress reports on the issue tracker of your team repo.
    4. Ensure your team members have the desired level of access to your team repo.
    5. Enable Travis CI for the team repo.
    6. Set up auto-publishing of docs. When set up correctly, your project website should be available via the URL https://cs2103-ay1819s2-{team-id}.github.io/main e.g., https://cs2103-ay1819s2-w13-1.github.io/main/. This also requires you to enable the GitHub Pages feature of your team repo and configure it to serve the website from the gh-pages branch.
    7. Create a team PR for us to track your project progress: i.e., create a PR from your team repo master branch to [nus-cs2103-AY1819S2/addressbook-level4] master branch. PR name: [Team ID] Product Name e.g., [T09-2] Contact List Pro.  As you merge code to your team repo's master branch, this PR will auto-update to reflect how much your team's product has progressed. In the PR description @mention the other team members so that they get notified when the tutor adds comments to the PR.

    All team members:

    1. Watch the main repo (created above) i.e., go to the repo and click on the watch button to subscribe to activities of the repo
    2. Fork the main repo to your personal GitHub account.
    3. Clone the fork to your Computer.
    4. Recommended: Set it up as an Intellij project (follow the instructions in the Developer Guide carefully).
    5. Set up the developer environment in your computer. You are recommended to use JDK 9 for AB-4 as some of the libraries used in AB-4 have not updated to support Java 10 yet. JDK 9 can be downloaded from the Java Archive.

    Note that some of our download scripts depend on the following folder paths. Please do not alter those paths in your project.

    • /src/main
    • /src/test
    • /docs

    Issue tracker setup

    We recommend you configure the issue tracker of the main repo as follows:

    • Delete existing labels and add the following labels.
      💡 Issue type labels are useful from the beginning of the project. The other labels are needed only when you start implementing the features.

    Issue type labels:

    • type.Epic : A big feature which can be broken down into smaller stories e.g. search
    • type.Story : A user story
    • type.Enhancement: An enhancement to an existing story
    • type.Task : Something that needs to be done, but not a story, bug, or an epic. e.g. Move testing code into a new folder)
    • type.Bug : A bug

    Status labels:

    • status.Ongoing : The issue is currently being worked on. note: remove this label before closing an issue.

    Priority labels:

    • priority.High : Must do
    • priority.Medium : Nice to have
    • priority.Low : Unlikely to do

    Bug Severity labels:

    • severity.Low : A flaw that is unlikely to affect normal operations of the product. Appears only in very rare situations and causes a minor inconvenience only.
    • severity.Medium : A flaw that causes occasional inconvenience to some users but they can continue to use the product.
    • severity.High : A flaw that affects most users and causes major problems for users. i.e., makes the product almost unusable for most users.
    • Create following milestones : v1.0v1.1v1.2v1.3v1.4,

    • You may configure other project settings as you wish. e.g. more labels, more milestones

    Project Schedule Tracking

    In general, use the issue tracker (Milestones, Issues, PRs, Tags, Releases, and Labels) for assigning, scheduling, and tracking all noteworthy project tasks, including user stories. Update the issue tracker regularly to reflect the current status of the project. You can also use GitHub's Projects feature to manage the project, but keep it linked to the issue tracker as much as you can.

    Using Issues:

    During the initial stages (latest by the start of v1.2):

    • Record each of the user stories you plan to deliver as an issue in the issue tracker. e.g. Title: As a user I can add a deadline
      Description: ... so that I can keep track of my deadlines

    • Assign the type.* and priority.* labels to those issues.

    • Formalize the project plan by assigning relevant issues to the corresponding milestone.

    From milestone v1.2:

    • Define project tasks as issues. When you start implementing a user story (or a feature), break it down to smaller tasks if necessary. Define reasonable sized, standalone tasks. Create issues for each of those tasks so that they can be tracked.e.g.

      • A typical task should be able to done by one person, in a few hours.

        • Bad (reasons: not a one-person task, not small enough): Write the Developer Guide
        • Good: Update class diagram in the Developer Guide for v1.4
      • There is no need to break things into VERY small tasks. Keep them as big as possible, but they should be no bigger than what you are going to assign a single person to do within a week. eg.,

        • Bad:Implementing parser (reason: too big).
        • Good:Implementing parser support for adding of floating tasks
      • Do not track things taken for granted. e.g., push code to repo should not be a task to track. In the example given under the previous point, it is taken for granted that the owner will also (a) test the code and (b) push to the repo when it is ready. Those two need not be tracked as separate tasks.

      • Write a descriptive title for the issue. e.g. Add support for the 'undo' command to the parser

        • Omit redundant details. In some cases, the issue title is enough to describe the task. In that case, no need to repeat it in the issue description. There is no need for well-crafted and detailed descriptions for tasks. A minimal description is enough. Similarly, labels such as priority can be omitted if you think they don't help you.

    • Assign tasks (i.e., issues) to the corresponding team members using the assignees field. Normally, there should be some ongoing tasks and some pending tasks against each team member at any point.

    • Optionally, you can use status.ongoing label to indicate issues currently ongoing.

    Using Milestones:

    We recommend you do proper milestone management starting from v1.2. Given below are the conditions to satisfy for a milestone to be considered properly managed:

    Planning a Milestone:

    • Issues assigned to the milestone, team members assigned to issues: Used GitHub milestones to indicate which issues are to be handled for which milestone by assigning issues to suitable milestones. Also make sure those issues are assigned to team members. Note that you can change the milestone plan along the way as necessary.

    • Deadline set for the milestones (in the GitHub milestone). Your internal milestones can be set earlier than the deadlines we have set, to give you a buffer.

    Wrapping up a Milestone:

    • A working product tagged with the correct tag (e.g. v1.2) and is pushed to the main repo
      or a product release done on GitHub. A product release is optional for v1.2 but required from from v1.3. Click here to see an example release.

    • All tests passing on Travis for the version tagged/released.

    • Milestone updated to match the product i.e. all issues completed and PRs merged for the milestone should be assigned to the milestone. Incomplete issues/PRs should be moved to a future milestone.

    • Milestone closed.

    • If necessary, future milestones are revised based on what you experienced in the current milestone  e.g. if you could not finish all issues assigned to the current milestone, it is a sign that you overestimated how much you can do in a week, which means you might want to reduce the issues assigned to future milestones to match that observation.

    As a user I can add a task by specifying a task description only, so that I can record tasks that need to be done ‘some day’. As a user I can find upcoming tasks, so that I can decide what needs to be done soon. As a user I can delete a task, so that I can get rid of tasks that I no longer care to track. As a new user I can view more information about a particular command, so that I can learn how to use various commands. As an advanced user I can use shorter versions of a command, so that type a command faster.


    • Step 2: Prioritize the user stories

      Suggested workflow:

      • Take one user story at a time and get team member opinions about it.

      • Based on the team consensus, put the story (i.e. the piece of paper) onto one of these three piles:

        • Must-Have : The product will be practically useless to the target user without this feature.
        • Nice-To-Have : The target user can benefit from this user story significantly but you are not certain if you'll have time to implement it.
        • Not-Useful : No significant benefit to the target user, or does not fit into the product vision.
      • If using physical paper to record user stories: After all stories have been put in the above three piles, you can make a record of which stories are in the three piles.

    • Step 3: Document requirements of the product

      Based on your user story categorization in the step above, given module requirements/constraints for the project, and the current state of the product, select which user stories you are likely to include in v2.0.

      Document the following items using a convenient format (e.g., a GoogleDoc). Do not spend time on formatting the content nicely; reason: these will be ported to the actual Developer Guide in your project repo later.
      💡 Some examples of these can be found in the AB4 Developer Guide.

      • Target user profile, value proposition, and user stories: Update the target user profile and value proposition to match the project direction you have selected. Give a list of the user stories (and update/delete existing ones, if applicable), including priorities. This can include user stories considered but will not be included in the final product.
      • Use cases: Give use cases (textual form) for a few representative user stories that need multiple steps to complete. e.g. Adding a tag to a person (assume the user needs to find the person first)
      • Non-functional requirements:
        Note: Many of the project constraints mentioned above are NFRs. You can add more. e.g. performance requirements, usability requirements, scalability requirements, etc.
      • Glossary: Define terms that are worth defining.
      • [Optional]Product survey: Explore a few similar/related products and describe your findings i.e. Pros, cons, (from the target user's point of view).
     

    Requirements → Specifying Requirements → Use Cases →

    Introduction

    Use Case: A description of a set of sequences of actions, including variants, that a system performs to yield an observable result of value to an actor.[ 📖 : uml-user-guideThe Unified Modeling Language User Guide, 2e, G Booch, J Rumbaugh, and I Jacobson ]

    Actor: An actor (in a use case) is a role played by a user. An actor can be a human or another system. Actors are not part of the system; they reside outside the system.

    A use case describes an interaction between the user and the system for a specific functionality of the system.

    • System: ATM
    • Actor: Customer
    • Use Case: Check account balance
      1. User inserts an ATM card
      2. ATM prompts for PIN
      3. User enters PIN
      4. ATM prompts for withdrawal amount
      5. User enters the amount
      6. ATM ejects the ATM card and issues cash
      7. User collects the card and the cash.
    • System: A Learning Management System (LMS)
    • Actor: Student
    • Use Case: Upload file
      1. Student requests to upload file
      2. LMS requests for the file location
      3. Student specifies the file location
      4. LMS uploads the file

    UML includes a diagram type called use case diagrams that can illustrate use cases of a system visually , providing a visual ‘table of contents’ of the use cases of a system. In the example below, note how use cases are shown as ovals and user roles relevant to each use case are shown as stick figures connected to the corresponding ovals.

    Unified Modeling Language (UML) is a graphical notation to describe various aspects of a software system. UML is the brainchild of three software modeling specialists James Rumbaugh, Grady Booch and Ivar Jacobson (also known as the Three Amigos). Each of them has developed their own notation for modeling software systems before joining force to create a unified modeling language (hence, the term ‘Unified’ in UML). UML is currently the de facto modeling notation used in the software industry.

    Use cases capture the functional requirements of a system.

     

    Requirements → Requirements →

    Non-Functional Requirements

    There are two kinds of requirements:

    1. Functional requirements specify what the system should do.
    2. Non-functional requirements specify the constraints under which system is developed and operated.

    Some examples of non-functional requirement categories:

    • Data requirements e.g. size, volatility, persistency etc.,
    • Environment requirements e.g. technical environment in which system would operate or need to be compatible with.
    • Accessibility, Capacity, Compliance with regulations, Documentation, Disaster recovery, Efficiency, Extensibility, Fault tolerance, Interoperability, Maintainability, Privacy, Portability, Quality, Reliability, Response time, Robustness, Scalability, Security, Stability, Testability, and more ...
    • Business/domain rules: e.g. the size of the minefield cannot be smaller than five.
    • Constraints: e.g. the system should be backward compatible with data produced by earlier versions of the system; system testers are available only during the last month of the project; the total project cost should not exceed $1.5 million.
    • Technical requirements: e.g. the system should work on both 32-bit and 64-bit environments.
    • Performance requirements: e.g. the system should respond within two seconds.
    • Quality requirements: e.g. the system should be usable by a novice who has never carried out an online purchase.
    • Process requirements: e.g. the project is expected to adhere to a schedule that delivers a feature set every one month.
    • Notes about project scope: e.g. the product is not required to handle the printing of reports.
    • Any other noteworthy points: e.g. the game should not use images deemed offensive to those injured in real mine clearing activities.

    We may have to spend an extra effort in digging NFRs out as early as possible because,

    1. NFRs are easier to miss  e.g., stakeholders tend to think of functional requirements first
    2. sometimes NFRs are critical to the success of the software.  E.g. A web application that is too slow or that has low security is unlikely to succeed even if it has all the right functionality.

    Given below are some requirements of TEAMMATES (an online peer evaluation system for education). Which one of these are non-functional requirements?

    • a. The response to any use action should become visible within 5 seconds.
    • b. The application admin should be able to view a log of user activities.
    • c. The source code should be open source.
    • d. A course should be able to have up to 2000 students.
    • e. As a student user, I can view details of my team members so that I can know who they are.
    • f. The user interface should be intuitive enough for users who are not IT-savvy.
    • g. The product is offered as a free online service.

    (a)(c)(d)(f)(g)

    Explanation: (b) are (e) are functions available for a specific user types. Therefore, they are functional requirements. (a), (c), (d), (f) and (g) are either constraints on functionality or constraints on how the project is done, both of which are considered non-functional requirements.

     

    Requirements → Specifying Requirements → Glossary →

    What

    Glossary: A glossary serves to ensure that all stakeholders have a common understanding of the noteworthy terms, abbreviation, acronyms etc.

    Here is a partial glossary from a variant of the Snakes and Ladders game:

    • Conditional square: A square that specifies a specific face value which a player has to throw before his/her piece can leave the square.
    • Normal square: a normal square does not have any conditions, snakes, or ladders in it.
     

    Requirements → Gathering Requirements →

    Product Surveys

    Studying existing products can unearth shortcomings of existing solutions that can be addressed by a new product. Product manuals and other forms of technical documentation of an existing system can be a good way to learn about how the existing solutions work.

    When developing a game for a mobile device, a look at a similar PC game can give insight into the kind of features and interactions the mobile game can offer.

    At this point we would like to ensure that you are able to create branch-based PRs without accidentally mixing commits between PRs (a common mistake) Therefore, we strongly encourage you to complete W3.3 (in particular, W3.3c) before attempting other exercises.

    There are no tutorials this week due to CNY.
    However, you are advised to set a time and meet with your team to complete the tasks for mid-v1.0 and start working towards completing the first draft of the user guide.

    Admin Appendix B (Policies) → Policy on plagiarism

    Policy on plagiarism

    We encourage sharing, but you should share with everyone in the class, not just a selected group. That is,

    • You are not allowed to share individual assignments with classmates directly.
    • You are not allowed to share project-related things with other teams directly.

    You can even reuse each other's work subject to the 'reuse policy' given below.

    If you submit code (or adopt ideas) taken from elsewhere, you need to comply with our reuse policy.

    Detection:

    • Detecting plagiarism in code is quite easy. You are not fooling anyone by reordering code or renaming methods/variables.
    • As all your work is publicly visible on GitHub, sooner or later somebody will notice the plagiarism.

    Penalties:

    • For submissions not affecting marks: We make a record of cases of plagiarism but we do not take further action. Such plagiarism does not disadvantage other students. Therefore, we prefer to spend all available resources on helping honest students to do better rather than to chase after dishonest students. If you think you gain something by plagiarizing, go ahead and do it. It's your choice and it's your loss.
    • For the final project/exam: Any case of claiming others' work as yours will be reported to the university for disciplinary action.

    Admin Appendix B (Policies) → Policy on reuse

    Policy on reuse

    Reuse is encouraged. However, note that reuse has its own costs (such as the learning curve, additional complexity, usage restrictions, and unknown bugs). Furthermore, you will not be given credit for work done by others. Rather, you will be given credit for using work done by others.

    • You are allowed to reuse work from your classmates, subject to following conditions:
      • The work has been published by us or the authors.
      • You clearly give credit to the original author(s).
    • You are allowed to reuse work from external sources, subject to following conditions:
      • The work comes from a source of 'good standing' (such as an established open source project). This means you cannot reuse code written by an outside 'friend'.
      • You clearly give credit to the original author. Acknowledge use of third party resources clearly e.g. in the welcome message, splash screen (if any) or under the 'about' menu. If you are open about reuse, you are less likely to get into trouble if you unintentionally reused something copyrighted.
      • You do not violate the license under which the work has been released. Please  do not use 3rd-party images/audio in your software unless they have been specifically released to be used freely. Just because you found it in the Internet does not mean it is free for reuse.
      • Always get permission from us before you reuse third-party libraries. Please post your 'request to use 3rd party library' in our forum. That way, the whole class get to see what libraries are being used by others.

    Giving credit for reused work

    Given below are how to give credit for things you reuse from elsewhere. These requirements are specific to this module  i.e., not applicable outside the module (outside the module you should follow the rules specified by your employer and the license of the reused work)

    If you used a third party library:

    • Mention in the README.adoc (under the Acknowledgements section)
    • mention in the Project Portfolio Page if the library has a significant relevance to the features you implemented

    If you reused code snippets found on the Internet  e.g. from StackOverflow answers or
    referred code in another software or
    referred project code by current/past student:

    • If you read the code to understand the approach and implemented it yourself, mention it as a comment
      Example:
      //Solution below adapted from https://stackoverflow.com/a/16252290
      {Your implmentation of the reused solution here ...}
      
    • If you copy-pasted a non-trivial code block (possibly with minor modifications  renaming, layout changes, changes to comments, etc.), also mark the code block as reused code (using @@author tags)
      Format:
      //@@author {yourGithubUsername}-reused
      //{Info about the source...}
      
      {Reused code (possibly with minor modifications) here ...}
      
      //@@author
      
      Example of reusing a code snippet (with minor modifications):
      persons = getList()
      //@@author johndoe-reused
      //Reused from https://stackoverflow.com/a/34646172 with minor modifications
      Collections.sort(persons, new Comparator<CustomData>() {
          @Override
          public int compare(CustomData lhs, CustomData rhs) {
              return lhs.customInt > rhs.customInt ? -1 : (lhs.customInt < rhs.customInt) ? 1 : 0;
          }
      });
      //@@author
      return persons;
      
     

    Adding @@author tags indicate authorship

    • Mark your code with a //@@author {yourGithubUsername}. Note the double @.
      The //@@author tag should indicates the beginning of the code you wrote. The code up to the next //@@author tag or the end of the file (whichever comes first) will be considered as was written by that author. Here is a sample code file:

      //@@author johndoe
      method 1 ...
      method 2 ...
      //@@author sarahkhoo
      method 3 ...
      //@@author johndoe
      method 4 ...
      
    • If you don't know who wrote the code segment below yours, you may put an empty //@@author (i.e. no GitHub username) to indicate the end of the code segment you wrote. The author of code below yours can add the GitHub username to the empty tag later. Here is a sample code with an empty author tag:

      method 0 ...
      //@@author johndoe
      method 1 ...
      method 2 ...
      //@@author
      method 3 ...
      method 4 ...
      
    • The author tag syntax varies based on file type e.g. for java, css, fxml. Use the corresponding comment syntax for non-Java files.
      Here is an example code from an xml/fxml file.

      <!-- @@author sereneWong -->
      <textbox>
        <label>...</label>
        <input>...</input>
      </textbox>
      ...
      
    • Do not put the //@@author inside java header comments.
      👎

      /**
        * Returns true if ...
        * @@author johndoe
        */
      

      👍

      //@@author johndoe
      /**
        * Returns true if ...
        */
      

    What to and what not to annotate

    • Annotate both functional and test code There is no need to annotate documentation files.

    • Annotate only significant size code blocks that can be reviewed on its own  e.g., a class, a sequence of methods, a method.
      Claiming credit for code blocks smaller than a method is discouraged but allowed. If you do, do it sparingly and only claim meaningful blocks of code such as a block of statements, a loop, or an if-else statement.

      • If an enhancement required you to do tiny changes in many places, there is no need to annotate all those tiny changes; you can describe those changes in the Project Portfolio page instead.
      • If a code block was touched by more than one person, either let the person who wrote most of it (e.g. more than 80%) take credit for the entire block, or leave it as 'unclaimed' (i.e., no author tags).
      • Related to the above point, if you claim a code block as your own, more than 80% of the code in that block should have been written by yourself. For example, no more than 20% of it can be code you reused from somewhere.
      • 💡 GitHub has a blame feature and a history feature that can help you determine who wrote a piece of code.
    • Do not try to boost the quantity of your contribution using unethical means such as duplicating the same code in multiple places. In particular, do not copy-paste test cases to create redundant tests. Even repetitive code blocks within test methods should be extracted out as utility methods to reduce code duplication. Individual members are responsible for making sure code attributed to them are correct. If you notice a team member claiming credit for code that he/she did not write or use other questionable tactics, you can email us (after the final submission) to let us know.

    • If you wrote a significant amount of code that was not used in the final product,

      • Create a folder called {project root}/unused
      • Move unused files (or copies of files containing unused code) to that folder
      • use //@@author {yourGithubUsername}-unused to mark unused code in those files (note the suffix unused) e.g.
      //@@author johndoe-unused
      method 1 ...
      method 2 ...
      

      Please put a comment in the code to explain why it was not used.

    • If you reused code from elsewhere, mark such code as //@@author {yourGithubUsername}-reused (note the suffix reused) e.g.

      //@@author johndoe-reused
      method 1 ...
      method 2 ...
      
    • You can use empty @@author tags to mark code as not yours when RepoSense attribute the to you incorrectly.

      • Code generated by the IDE/framework, should not be annotated as your own.

      • Code you modified in minor ways e.g. adding a parameter. These should not be claimed as yours but you can mention these additional contributions in the Project Portfolio page if you want to claim credit for them.

     

    At the end of the project each student is required to submit a Project Portfolio Page.

    • Objective:

      • For you to use  (e.g. in your resume) as a well-documented data point of your SE experience
      • For us to use as a data point to evaluate your,
        • contributions to the project
        • your documentation skills
    • Sections to include:

      • Overview: A short overview of your product to provide some context to the reader.

      • Summary of Contributions:

        • Code contributed: Give a link to your code on Project Code Dashboard, which should be https://nus-cs2103-ay1819s2.github.io/cs2103-dashboard/#=undefined&search=githbub_username_in_lower_case (replace githbub_username_in_lower_case with your actual username in lower case e.g., johndoe). This link is also available in the Project List Page -- linked to the icon under your photo.
        • Features implemented: A summary of the features you implemented. If you implemented multiple features, you are recommended to indicate which one is the biggest feature.
        • Other contributions:
          • Contributions to project management e.g., setting up project tools, managing releases, managing issue tracker etc.
          • Evidence of helping others e.g. responses you posted in our forum, bugs you reported in other team's products,
          • Evidence of technical leadership e.g. sharing useful information in the forum
      • Contributions to the User Guide: Reproduce the parts in the User Guide that you wrote. This can include features you implemented as well as features you propose to implement.
        The purpose of allowing you to include proposed features is to provide you more flexibility to show your documentation skills. e.g. you can bring in a proposed feature just to give you an opportunity to use a UML diagram type not used by the actual features.

      • Contributions to the Developer Guide: Reproduce the parts in the Developer Guide that you wrote. Ensure there is enough content to evaluate your technical documentation skills and UML modelling skills. You can include descriptions of your design/implementations, possible alternatives, pros and cons of alternatives, etc.

      • If you plan to use the PPP in your Resume, you can also include your SE work outside of the module (will not be graded)

    • Format:

      • File name: docs/team/githbub_username_in_lower_case.adoc e.g., docs/team/johndoe.adoc

      • Follow the example in the AddressBook-Level4

      • 💡 You can use the Asciidoc's include feature to include sections from the developer guide or the user guide in your PPP. Follow the example in the sample.

      • It is assumed that all contents in the PPP were written primarily by you. If any section is written by someone else  e.g. someone else wrote described the feature in the User Guide but you implemented the feature, clearly state that the section was written by someone else  (e.g. Start of Extract [from: User Guide] written by Jane Doe).  Reason: Your writing skills will be evaluated based on the PPP

    • Page limit:

      Content Limit
      Overview + Summary of contributions 0.5-1 (soft limit)
      Contributions to the User Guide 1-3 (soft limit)
      Contributions to the Developer Guide 3-6 (soft limit)
      Total 5-10 (strict)
      • The page limits given above are after converting to PDF format. The actual amount of content you require is actually less than what these numbers suggest because the HTML → PDF conversion adds a lot of spacing around content.
      • Reason for page limit: These submissions are peer-graded (in the PE) which needs to be done in a limited time span.
        If you have more content than the limit given above, you can give a representative samples of UG and DG that showcase your documentation skills. Those samples should be understandable on their own. For the parts left-out, you can give an abbreviated version and refer the reader to the full UG/DG for more details.
        It's similar to giving extra details as appendices; the reader will look at the UG/DG if the PPP is not enough to make a judgment. For example, when judging documentation quality, if the part in the PPP is not well-written, there is no point reading the rest in the main UG/DG. That's why you need to put the most representative part of your writings in the PPP and still give an abbreviated version of the rest in the PPP itself. Even when judging the quantity of work, the reader should be able to get a good sense of the quantity by combining what is quoted in the PPP and your abbreviated description of the missing part. There is no guarantee that the evaluator will read the full document.

    Admin Appendix B (Policies) → Policy on help from outsiders

    Policy on help from outsiders

    In general, you are not allowed to involve outsiders in your project except your team members and the teaching team. However, It is OK to give your product to others for the purpose of getting voluntary user feedback. It is also OK to learn from others as long as they don't do your project work themselves.

    Admin Exams

    There is no midterm.

    The final exam has two parts:

    • Part 1: MCQ questions (1 hour, 20 marks)
    • Part 2: Essay questions (1 hour, 20 marks)

    Both papers will be given to you at the start but you need to answer Part 1 first (i.e. MCQ paper). It will be collected 1 hour after the exam start time (even if arrived late for the exam). You are free to start part 2 early if you finish Part 1 early.

    Final Exam: Part 1 (MCQ)

    Each MCQ question gives you a statement to evaluate.

    An example statement

    Testing is a Q&A activity

    Unless stated otherwise, the meaning of answer options are
    A: Agree. If the question has multiple statements, agree with all of them.
    B: Disagree. If the question has multiple statements, disagree with at least one of them
    C, D, E: Not used

    Number of questions: 100

    Note that you have slightly more than ½ minute for each question, which means you need to go through the questions fairly quickly.

    Given the fast pace required by the paper, to be fair to all students, you will not be allowed to clarify doubts about questions (in Part 1) by talking to invigilators.

    • If a question is not clear, you can circle the question number in the question paper and write your doubt in the question paper, near that question.
    • If your doubt is justified (e.g. there is a typo in the question) or if many students found the question to be unclear, the examiner may decide to omit that question from grading.

    Questions in Part 1 are confidential. You are not allowed to reveal Part 1 content to anyone after the exam. All pages of the assessment paper are to be returned at the end of the exam.

    You will be given OCR forms (i.e., bubble sheets) to indicate your answers for Part 1. As each OCR form can accommodate only 50 answers, you will be given 2 OCR forms. Indicate your student number in both OCR forms.

    To save space, we use the following notation in MCQ question. [x | y | z] means ‘x and z, but not y’

    SE is [boring | useful | fun] means SE is not boring AND SE is useful AND SE is fun.

    Consider the following statement:

    • IDEs can help with [writing | debugging | testing] code.

    The correct response for it is Disagree because IDEs can help with all three of the given options, not just writing and testing.

    Some questions will use underlines or highlighting to draw your attention to a specific part of the question. That is because those parts are highly relevant to the answer and we don’t want you to miss the relevance of that part.

    Consider the statement below:

    Technique ABC can be used to generate more test cases.

    The word can is underlined because the decision you need to make is whether the ABC can or cannot be used to generate more test cases; the decision is not whether ABC can be used to generate more or better test cases.

    Markers such as the one given below appears at left margin of the paper to indicate where the question corresponds to a new column in the OCR form. E.g. questions 11, 21, 31, etc. (a column has 10 questions). Such markers can help you to detect if you missed a question in the previous 10 questions. You can safely ignore those markers if you are not interested in making use of that additional hint.


    Some questions have tags e.g., the question below has a tag JAVA. These tags provide additional context about the question. In the example below, the tag indicates that the code given in the question is Java code.


    The exam paper is open-book: you may bring any printed or written materials to the exam in hard copy format. However, given the fast pace required by Part 1, you will not have time left to refer notes during that part of the exam.

    💡 Mark the OCR form as you go, rather than planning to transfer your answers to the OCR form near the end.  Reason: Given there are 100 questions, it will be hard to estimate how much time you need to mass-transfer all answers to OCR forms.

    💡 Write the answer in the exam paper as well when marking it in the OCR form.  Reason: It will reduce the chance of missing a question. Furthermore, in case you missed a question, it will help you correct the OCR form quickly.

    💡 We have tried to avoid deliberately misleading/tricky questions. If a question seems to take a very long time to figure out, you are probably over-thinking it.

    You will be given a practice exam paper to familiarize yourself with this slightly unusual exam format.

    Final Exam: Part 2 (Essay)

    Unlike in part 1, you can ask invigilators for clarifications if you found a question to be unclear in part 2.

    Yes, you may use pencils when answering part 2.

    Admin Appendix C (FAQs) → What if I don’t carry around a laptop?

    What if I don’t carry around a laptop?

    If you do not have a laptop or prefer not to bring the laptop, it is up to you to show your work to the tutor in some way (e.g. by connecting to your home PC remotely), without requiring extra time/effort from the tutor or team members.

    Reason: As you enjoy the benefits of not bring the laptop; you (not others) should bear the cost too.

    Admin Appendix B (Policies) → Policy on publishing submissions

    Policy on publishing submissions

    The source code are publicly available and are available for reuse by others without any restrictions. 
    Is publishing submissions unfair to the team? We don't think so. If you were the first to think of something your peers are willing to adopt later, that means you are already ahead of them and they are unlikely to earn more marks by adopting your ideas.