This site is from a past semester! The current version will be here when the new semester starts.
CS2103/T 2020 Aug-Dec
  • Full Timeline
  • Week 1 [Mon, Aug 10th]
  • Week 2 [Fri, Aug 14th]
  • Week 3 [Fri, Aug 21st]
  • Week 4 [Fri, Aug 28th]
  • Week 5 [Fri, Sep 4th]
  • Week 6 [Fri, Sep 11th]
  • Week 7 [Fri, Sep 18th]
  • Week 8 [Fri, Oct 2nd]
  • Week 9 [Fri, Oct 9th]
  • Week 10 [Fri, Oct 16th]
  • Week 11 [Fri, Oct 23rd]
  • Week 12 [Fri, Oct 30th]
  • Week 13 [Fri, Nov 6th]
  • Textbook
  • Admin Info
  • Dashboards
  •  Individual Project (iP):
  • Individual Project Info
  • iP Upstream Repo
  • iP Showcase
  • iP Code Dashboard
  • iP Progress Dashboard

  •  Team Project (tP):
  • Team Project Info
  • Addressbook-level3
  • Team List
  • tP Code Dashboard
  • tP Progress Dashboard
  • Report Bugs
  • Forum
  • Gitter (Chat)
  • Instructors
  • Announcements
  • Files
  • Tutorial Schedule
  • Java Coding Standard
  • Git Conventions
  • Forum Activities Dashboard
  • Participation Dashboard
  • Week 7 [Fri, Sep 18th] - Topics

    • [W7.1] Requirements: Use Cases
    • [W7.1a] Requirements → Specifying Requirements → Use Cases → Introduction

    • [W7.1b] Requirements → Specifying Requirements → Use Cases → Identifying

    • [W7.1c] Requirements → Specifying Requirements → Use Cases → Details

    • [W7.1d] Requirements → Specifying Requirements → Use Cases → Usage

    • [W7.2] Design: High-Level View

       Introduction

    • [W7.2a] Design → Introduction → What

       Design Approaches

    • [W7.2b] Design → Design Approaches → Top-down and bottom-up design

    • [W7.2c] Design Approaches → Agile Design → Agile design

    • [W7.3] Design: Fundamentals

       Abstraction

    • [W7.3a] Design → Design Fundamentals → Abstraction → What

       Coupling

    • [W7.3b] Design → Design Fundamentals → Coupling → What

    • [W7.3c] Design → Design Fundamentals → Coupling → How

    • [W7.3d] Design → Design Fundamentals → Coupling → Types of coupling : OPTIONAL

       Cohesion

    • [W7.3e] Design → Design Fundamentals → Cohesion → What

    • [W7.3f] Design → Design Fundamentals → Cohesion → How

    • [W7.4] IDEs: Advanced Features : OPTIONAL
    • [W7.4a] Tools → IntelliJ IDEA → Productivity shortcuts : OPTIONAL
    • [W7.5] Integration Approaches
    • [W7.5a] Implementation → Integration → Approaches → Late and one time versus early and frequent

    • [W7.5b] Implementation → Integration → Approaches → Big-bang versus incremental integration

    • [W7.5c] Implementation → Integration → Approaches → Top-down versus bottom-up integration : OPTIONAL

    • [W7.6] Project Mgt: Scheduling and Tracking
    • [W7.6a] Project Management → Project Planning → Milestones

    • [W7.6b] Project Management → Project Planning → Buffers

    • [W7.6c] Project Management → Project Planning → Issue trackers

    • [W7.6d] Project Management → Project Planning → Work breakdown structure

    • [W7.6e] Project Management → Project Planning → Gantt charts

    • [W7.6f] Project Management → Project Planning → PERT charts : OPTIONAL

    • [W7.6g] Project Management → Teamwork → Team structures

    • [W7.7] Project Mgt: Workflows
    • [W7.7a] Project Management → Revision Control → Forking flow

    • [W7.7b] Tools → Git and GitHub → Forking workflow

    • [W7.7c] Project Management → Revision Control → DRCS vs CRCS

    • [W7.7d] Project Management → Revision Control → Feature branch flow : OPTIONAL

    • [W7.7e] Project Management → Revision Control → Centralized flow : OPTIONAL


    Guidance for the item(s) below:

    Previously, you learned a number of techniques for specifying requirements. There's one more left, which we'll cover this week.

    [W7.1] Requirements: Use Cases

    Video

    W7.1a

    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: 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. User confirms.
      6. OBS transfers the money and displays the new account balance.
      Use case ends.
    
    Extensions:
      3a. OBS detects an error in the entered data.
          3a1. OBS requests for the correct data.
          3a2. User enters new data.
          Steps 3a1-3a2 are repeated until the data entered are correct.
          Use case resumes from step 4.
      
      3b. User requests to effect the transfer in a future date.
          3b1. OBS requests for confirmation.
          3b2. User confirms future transfer.
          Use case ends.
      
      *a. At any time, User chooses to cancel the transfer.
          *a1. OBS requests to confirm the cancellation.
          *a2. User confirms the cancellation.
          Use case ends.
    
    • 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 on the right, 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 had developed their own notation for modeling software systems before joining forces 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.

    W7.1b

    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, an exam management systemExamSys, a library management systemLibSys.

    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 of which level of detail you are working at 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 is editing the bug report 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 mean ‘assign bug report’ or are there other types 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.

    W7.1c

    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 a 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 minimize 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 it 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: SquareGame
    Use case: Each use case can be given a unique identification for easier cross reference. 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 a die.
    6. Current Player adjusts the throw speed.
    7. Current Player triggers the die throw.
    8. SquareGame shows the face value of the die.
    9. SquareGame 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. SquareGame 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.

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

    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.

    Use case ends.

    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. User confirms.
      6. OBS transfers the money and displays the new account balance.
      Use case ends.
    
    Extensions:
      3a. OBS detects an error in the entered data.
          3a1. OBS requests for the correct data.
          3a2. User enters new data.
          Steps 3a1-3a2 are repeated until the data entered are correct.
          Use case resumes from step 4.
      
      3b. User requests to effect the transfer in a future date.
          3b1. OBS requests for confirmation.
          3b2. User confirms future transfer.
          Use case ends.
      
      *a. At any time, User chooses to cancel the transfer.
          *a1. OBS requests to confirm the cancellation.
          *a2. User confirms the cancellation.
          Use case ends.
    
      *b. At any time, 120 seconds lapse without any input from the User.
          *b1. OBS cancels the transfer.
          *b2. OBS informs the User of the cancellation.
          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.

    You use a dotted arrow and an <<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 you 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.
      ...

    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.
      ...

    Complete the following use case (MSS, extensions, etc.). Note that you should not blindly follow how the existing A type of a cash card topup machineEZ-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: UC01 top-up EZ-Link card
    • Actor: EZ-Link card user
    • System: EZ-Link machine (those found at MRTs)
    • Use case: UC01 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: UC01 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.

    W7.1d

    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.

    You are recommended to 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 do 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 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 cases 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.

    Follow up notes for the item(s) above:

    Now that you know all the different ways of specifying requirements, here is an example that shows how all techniques of specifying requirements can work together:

    Video Example: TeamFormer

    Guidance for the item(s) below:

    In the tP, you start with a code base that already has a certain design. What if there is no such design for you to starth with? The next few topics look at how one can come up with such a design yourself.

    [W7.2] Design: High-Level View

    Video


    Introduction

    W7.2a

    Design → Introduction → What

    Can explain what is software design

    Design is the creative process of transforming the problem into a solution; the solution is also called design. -- 📖 Software Engineering Theory and Practice, Shari Lawrence; Atlee, Joanne M. Pfleeger

    Software design has two main aspects:

    • Product/external design: designing the external behavior of the product to meet the users' requirements. This is usually done by product designers with input from business analysts, user experience experts, user representatives, etc.
    • Implementation/internal design: designing how the product will be implemented to meet the required external behavior. This is usually done by software architects and software engineers.

    Follow up notes for the item(s) above:

    Now that you know there are two kinds of 'design', also note that this module focuses more on the internal design rather than the external design.


    Design Approaches

    W7.2b

    Design → Design Approaches → Top-down and bottom-up design

    Can explain top-down and bottom-up design

    Multi-level design can be done in a top-down manner, bottom-up manner, or as a mix.

    • Top-down: Design the high-level design first and flesh out the lower levels later. This is especially useful when designing big and novel systems where the high-level design needs to be stable before lower levels can be designed.
    • Bottom-up: Design lower level components first and put them together to create the higher-level systems later. This is not usually scalable for bigger systems. One instance where this approach might work is when designing a variation of an existing system or re-purposing existing components to build a new system.
    • Mix: Design the top levels using the top-down approach but switch to a bottom-up approach when designing the bottom levels.

    Top-down design is better than bottom-up design.

    False

    Explanation: Not necessarily. It depends on the situation. Bottom-up design may be preferable when there are a lot of existing components we want to reuse.

    W7.2c

    Design Approaches → Agile Design → Agile design

    Can explain agile design

    Agile design can be contrasted with full upfront design in the following way:

    Agile designs are emergent, they’re not defined up front. Your overall system design will emerge over time, evolving to fulfill new requirements and take advantage of new technologies as appropriate. Although you will often do some initial architectural modeling at the very beginning of a project, this will be just enough to get your team going. This approach does not produce a fully documented set of models in place before you may begin coding. -- adapted from agilemodeling.com

    The agile design camp expects the design to change over the product’s lifetime.

    True

    Explanation: Yes, that is why they do not believe in spending too much time creating a detailed and full design at the very beginning. However, the architecture is expected to remain relatively stable even in the agile design approach.

    Guidance for the item(s) below:

    As you do projects, you'll have to make design decisions e.g., decide between multiple design alternatives. Let us learn three fundamental design concepts that you can use in those decisions.

    It is extremely important for you to know these three because they are like the DNA of every higher-level design concept.

    [W7.3] Design: Fundamentals

    Video


    Abstraction

    W7.3a

    Design → Design Fundamentals → Abstraction → What

    Can explain abstraction

    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 need 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.

    Data abstraction: abstracting away the lower level data items and thinking in terms of bigger entities

    Within a certain software component, you 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: abstracting away details of the actual control flow to focus on tasks at a higher 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 abstraction.

    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 level 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.


    Coupling

    W7.3b

    Design → Design Fundamentals → Coupling → What

    Can explain coupling

    Coupling is a measure of the degree of dependence between components, classes, methods, etc. Low coupling indicates that a component is less dependent on other components. High coupling (aka tight coupling or strong coupling) is discouraged due to the following disadvantages:

    • Maintenance is harder because a change in one module could cause changes in other modules coupled to it (i.e. a ripple effect).
    • Integration is harder because multiple components coupled with each other have to be integrated at the same time.
    • Testing and reuse of the module is harder due to its dependence on other modules.

    In the example below, design A appears to have more coupling between the components than design B.

    Discuss the coupling levels of alternative designs x and y.

    Overall coupling levels in x and y seem to be similar (neither has more dependencies than the other). (Note that the number of dependency links is not a definitive measure of the level of coupling. Some links may be stronger than the others.). However, in x, A is highly-coupled to the rest of the system while B, C, D, and E are standalone (do not depend on anything else). In y, no component is as highly-coupled as A of x. However, only D and E are standalone.

    Explain the link (if any) between regressions and coupling.

    When the system is highly-coupled, the risk of regressions is higher too e.g. when component A is modified, all components ‘coupled’ to component A risk ‘unintended behavioral changes’.

    Discuss the relationship between coupling and a measure of how easily a given component can be testedtestability.

    Coupling decreases testability because if the Software Under TestSUT is coupled to many other components, it becomes difficult to test the SUT in isolation of its dependencies.

    Choose the correct statements.

    • a. As coupling increases, testability decreases.
    • b. As coupling increases, the risk of regression increases.
    • c. As coupling increases, the value of automated regression testing increases.
    • d. As coupling increases, integration becomes easier as everything is connected together.
    • e. As coupling increases, maintainability decreases.

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

    Explanation: High coupling means either more components are required to be integrated at once in a big-bang fashion (increasing the risk of things going wrong) or more drivers and stubs are required when integrating incrementally.

    W7.3c

    Design → Design Fundamentals → Coupling → How

    Can reduce coupling

    X is coupled to Y if a change to Y can potentially require a change in X.

    If the Foo class calls the method Bar#read(), Foo is coupled to Bar because a change to Bar can potentially (but not always) require a change in the Foo class e.g. if the signature of Bar#read() is changed, Foo needs to change as well, but a change to the Bar#write() method may not require a change in the Foo class because Foo does not call Bar#write().

    class Foo {
    ...
    new Bar().read();
    ...
    }

    class Bar {
    void read() {
    ...
    }

    void write() {
    ...
    }
    }

    Some examples of coupling: A is coupled to B if,

    • A has access to the internal structure of B (this results in a very high level of coupling)
    • A and B depend on the same global variable
    • A calls B
    • A receives an object of B as a parameter or a return value
    • A inherits from B
    • A and B are required to follow the same data format or communication protocol

    Which of these indicate coupling between components A and B?

    • a. component A has access to the internal structure of component B.
    • b. components A and B are written by the same developer.
    • c. component A calls component B.
    • d. component A receives an object of component B as a parameter.
    • e. component A inherits from component B.
    • f. components A and B have to follow the same data format or communication protocol.

    (a)(b)(c)(d)(e)(f)

    Explanation: Being written by the same developer does not imply coupling.

    W7.3d : OPTIONAL

    Design → Design Fundamentals → Coupling → Types of coupling

    Can identify types of coupling

    Some examples of different coupling types:

    • Content coupling: one module modifies or relies on the internal workings of another module e.g., accessing local data of another module
    • Common/Global coupling: two modules share the same global data
    • Control coupling: one module controlling the flow of another, by passing it information on what to do e.g., passing a flag
    • Data coupling: one module sharing data with another module e.g. via passing parameters
    • External coupling: two modules share an externally imposed convention e.g., data formats, communication protocols, device interfaces.
    • Subclass coupling: a class inherits from another class. Note that a child class is coupled to the parent class but not the other way around.
    • Temporal coupling: two actions are bundled together just because they happen to occur at the same time e.g. extracting a contiguous block of code as a method although the code block contains statements unrelated to each other


    Cohesion

    W7.3e

    Design → Design Fundamentals → Cohesion → What

    Can explain cohesion

    Cohesion is a measure of how strongly-related and focused the various responsibilities of a component are. A highly-cohesive component keeps related functionalities together while keeping out all other unrelated things.

    Higher cohesion is better. Disadvantages of low cohesion (aka weak cohesion):

    • Lowers the understandability of modules as it is difficult to express module functionalities at a higher level.
    • Lowers maintainability because a module can be modified due to unrelated causes (reason: the module contains code unrelated to each other) or many modules may need to be modified to achieve a small change in behavior (reason: because the code related to that change is not localized to a single module).
    • Lowers reusability of modules because they do not represent logical units of functionality.

    W7.3f

    Design → Design Fundamentals → Cohesion → How

    Can increase cohesion

    Cohesion can be present in many forms. Some examples:

    • Code related to a single concept is kept together, e.g. the Student component handles everything related to students.
    • Code that is invoked close together in time is kept together, e.g. all code related to initializing the system is kept together.
    • Code that manipulates the same data structure is kept together, e.g. the GameArchive component handles everything related to the storage and retrieval of game sessions.

    Suppose a Payroll application contains a class that deals with writing data to the database. If the class includes some code to show an error dialog to the user if the database is unreachable, that class is not cohesive because it seems to be interacting with the user as well as the database.

    Compare the cohesion of the following two versions of the EmailMessage class. Which one is more cohesive and why?

    // version-1
    class EmailMessage {
    private String sendTo;
    private String subject;
    private String message;

    public EmailMessage(String sendTo, String subject, String message) {
    this.sendTo = sendTo;
    this.subject = subject;
    this.message = message;
    }

    public void sendMessage() {
    // sends message using sendTo, subject and message
    }
    }

    // version-2
    class EmailMessage {
    private String sendTo;
    private String subject;
    private String message;
    private String username;

    public EmailMessage(String sendTo, String subject, String message) {
    this.sendTo = sendTo;
    this.subject = subject;
    this.message = message;
    }

    public void sendMessage() {
    // sends message using sendTo, subject and message
    }

    public void login(String username, String password) {
    this.username = username;
    // code to login
    }
    }

    Version 2 is less cohesive.

    Explanation: Version 2 is handling functionality related to login, which is not directly related to the concept of ‘email message’ that the class is supposed to represent. On a related note, you can improve the cohesion of both versions by removing the sendMessage functionality. Although sending messages is related to emails, this class is supposed to represent an email message, not an email server.

    Guidance for the item(s) below:

    In case you are the type who want to become a 'power user' of IDEs (it's not a bad idea, given the IDE is like the primary tool of a software engineer), given below are some more things you can do with IDEs.

    [W7.4] IDEs: Advanced Features : OPTIONAL

    W7.4a : OPTIONAL

    Tools → IntelliJ IDEA → Productivity shortcuts

    Can use some useful IDE productivity shortcuts

    Guidance for the item(s) below:

    As you start adding new code to the tP, let's also become aware of various approaches in integrating new code to a product.

    [W7.5] Integration Approaches

    Video

    W7.5a

    Implementation → Integration → Approaches → Late and one time versus early and frequent

    Can explain how integration approaches vary based on timing and frequency

    In terms of timing and frequency, there are two general approaches to integration: late and one-time, early and frequent.

    Late and one-time: wait till all components are completed and integrate all finished components near the end of the project.

    This approach is not recommended because integration often causes many component incompatibilities (due to previous miscommunications and misunderstandings) to surface which can lead to delivery delays i.e. Late integration → incompatibilities found → major rework required → cannot meet the delivery date.

    Early and frequent: integrate early and evolve each part in parallel, in small steps, re-integrating frequently.

    A it has all the high-level components needed for the first version in their minimal form, compiles, and runs but may not produce any useful output yetwalking skeleton can be written first. This can be done by one developer, possibly the one in charge of integration. After that, all developers can flesh out the skeleton in parallel, adding one feature at a time. After each feature is done, simply integrate the new code into the main system.

    Here is an animation that compares the two approaches:

    W7.5b

    Implementation → Integration → Approaches → Big-bang versus incremental integration

    Can explain how integration approaches vary based on amount merged at a time

    Big-bang integration: integrate all components at the same time.

    Big-bang is not recommended because it will uncover too many problems at the same time which could make debugging and bug-fixing more complex than when problems are uncovered incrementally.

    Incremental integration: integrate a few components at a time. This approach is better than big-bang integration because it surfaces integration problems in a more manageable way.

    Here is an animation that compares the two approaches:

    Give two arguments in support and two arguments against the following statement.

    Because there is no external client, it is OK to use big bang integration for a school project.

    Arguments for:

    • It is relatively simple; even big-bang can succeed.
    • Project duration is short; there is not enough time to integrate in steps.
    • The system is non-critical, non-production (demo only); the cost of integration issues is relatively small.

    Arguments against:

    • Inexperienced developers; big-bang more likely to fail.
    • Too many problems may be discovered too late. Submission deadline (fixed) can be missed.
    • Team members have not worked together before; increases the probability of integration problems.

    W7.5c : OPTIONAL

    Implementation → Integration → Approaches → Top-down versus bottom-up integration

    Can explain how integration approaches vary based on the order of integration

    Based on the order in which components are integrated, incremental integration can be done in three ways.

    Top-down integration: higher-level components are integrated before bringing in the lower-level components. One advantage of this approach is that higher-level problems can be discovered early. One disadvantage is that this requires the use of stubs in place of lower level components until the real lower-level components are integrated into the system. Otherwise, higher-level components cannot function as they depend on lower level ones.

    Stub: A stub has the same interface as the component it replaces, but its implementation is so simple that it is unlikely to have any bugs. It mimics the responses of the component, but only for a limited set of predetermined inputs. That is, it does not know how to respond to any other inputs. Typically, these mimicked responses are hard-coded in the stub rather than computed or retrieved from elsewhere, e.g. from a database.

    Bottom-up integration: the reverse of top-down integration. Note that when integrating lower level components, additional code written to provide inputs to a component via an APIdrivers may be needed to test the integrated components because the UI may not be integrated yet, just like how top-down integration needs stubs.

    Sandwich integration: a mix of the top-down and bottom-up approaches. The idea is to do both top-down and bottom-up so as to 'meet' in the middle.

    Here is an animation that compares the three approaches:

    Suggest an integration strategy for the system represented by the following diagram. You need not follow a strict top-down, bottom-up, sandwich, or big bang approach. Dashed arrows represent dependencies between classes.

    Also take into account the following facts in your test strategy:

    • HospitalUI will be developed early, so as to get customer feedback early.
    • HospitalFacade shields the UI from the complexities of the application layer. It simply redirects the method calls received to the appropriate classes below.
    • IO_Helper is to be reused from an earlier project, with minor modifications.
    • Development of the OutPatient component has been outsourced, and its delivery is not expected until the 2nd half of the project.

    There can be many acceptable answers to this question. But any good strategy should consider at least some of the following:

    • Because HospitalUI will be developed early, it’s OK to integrate it early, using stubs, rather than wait for the rest of the system to finish. (i.e. a top-down integration is suitable for HospitalUI)
    • Because HospitalFacade is unlikely to have a lot of business logic, it may not be worth to write stubs to test it (i.e. a bottom-up integration is better for HospitalFacade).
    • Because IO_Helper is to be reused from an earlier project, you can finish it early. This is especially suitable since there are many classes that use it. Therefore IO_Helper can be integrated with the dependent classes in bottom-up fashion.
    • Because the OutPatient class may be delayed, you may have to integrate PatientMgr using a stub.
    • TypeA, TypeB, and TypeC seem to be tightly coupled. It may be a good idea to test them together.

    Given below is one possible integration test strategy. The relative positioning of items is used to indicate a rough timeline.

    Consider the architecture given below. Describe the order in which components will be integrated with one another if the following integration strategies were adopted.

    a) top-down
    b) bottom-up
    c) sandwich

    Note that dashed arrows show dependencies (e.g. A depends on B, C and D, and is therefore higher-level than B, C and D).

    a) Diagram:

    b) Diagram:

    c) Diagram:

    Guidance for the item(s) below:

    Coordinating a team project is not easy. Given below are some very basic tools and techniques that are often used in planning, scheduling, and tracking projects.

    [W7.6] Project Mgt: Scheduling and Tracking

    Video

    W7.6a

    Project Management → Project Planning → Milestones

    Can explain milestones

    A milestone is the end of a stage which indicates significant progress. You should take into account dependencies and priorities when deciding on the features to be delivered at a certain milestone.

    Each intermediate product release is a milestone.

    In some projects, it is not practical to have a very detailed plan for the whole project due to the uncertainty and unavailability of required information. In such cases, you can use a high-level plan for the whole project and a detailed plan for the next few milestones.

    Milestones for the Minesweeper project, iteration 1

    Day Milestones
    Day 1 Architecture skeleton completed
    Day 3 ‘new game’ feature implemented
    Day 4 ‘new game’ feature tested

    W7.6b

    Project Management → Project Planning → Buffers

    Can explain buffers

    A buffer is time set aside to absorb any unforeseen delays. It is very important to include buffers in a software project schedule because effort/time estimations for software development are notoriously hard. However, do not inflate task estimates to create hidden buffers; have explicit buffers instead. Reason: With explicit buffers, it is easier to detect incorrect effort estimates which can serve as feedback to improve future effort estimates.

    W7.6c

    Project Management → Project Planning → Issue trackers

    Can explain issue trackers

    Keeping track of project tasks (who is doing what, which tasks are ongoing, which tasks are done etc.) is an essential part of project management. In small projects, it may be possible to keep track of tasks using simple tools such as online spreadsheets or general-purpose/light-weight task tracking tools such as Trello. Bigger projects need more sophisticated task tracking tools.

    Issue trackers (sometimes called bug trackers) are commonly used to track task assignment and progress. Most online project management software such as GitHub, SourceForge, and BitBucket come with an integrated issue tracker.

    A screenshot from the Jira Issue tracker software (Jira is part of the BitBucket project management tool suite):

    W7.6d

    Project Management → Project Planning → Work breakdown structure

    Can explain work breakdown structures

    A Work Breakdown Structure (WBS) depicts information about tasks and their details in terms of subtasks. When managing projects, it is useful to divide the total work into smaller, well-defined units. Relatively complex tasks can be further split into subtasks. In complex projects, a WBS can also include prerequisite tasks and effort estimates for each task.

    The high level tasks for a single iteration of a small project could look like the following:

    Task ID Task Estimated Effort Prerequisite Task
    A Analysis 1 man day -
    B Design 2 man day A
    C Implementation 4.5 man day B
    D Testing 1 man day C
    E Planning for next version 1 man day D

    The effort is traditionally measured in man hour/day/month i.e. work that can be done by one person in one hour/day/month. The Task ID is a label for easy reference to a task. Simple labeling is suitable for a small project, while a more informative labeling system can be adopted for bigger projects.

    An example WBS for a game development project.

    Task ID Task Estimated Effort Prerequisite Task
    A High level design 1 man day -
    B Detail design
    1. User Interface
    2. Game Logic
    3. Persistency Support
    2 man day
    • 0.5 man day
    • 1 man day
    • 0.5 man day
    A
    C Implementation
    1. User Interface
    2. Game Logic
    3. Persistency Support
    4.5 man day
    • 1.5 man day
    • 2 man day
    • 1 man day
    • B.1
    • B.2
    • B.3
    D System Testing 1 man day C
    E Planning for next version 1 man day D

    All tasks should be well-defined. In particular, it should be clear as to when the task will be considered done.

    Some examples of ill-defined tasks and their better-defined counterparts:

    Bad Better
    more coding implement component X
    do research on UI testing find a suitable tool for testing the UI

    Which one these project tasks is not well-defined?

    (c)

    Explanation: ‘More testing’ is not well-defined. How much is ‘more’? ‘Test the delete functionality’ is a better-defined task.

    W7.6e

    Project Management → Project Planning → Gantt charts

    Can explain Gantt charts

    A Gantt chart is a 2-D bar-chart, drawn as time vs tasks (represented by horizontal bars).

    A sample Gantt chart:

    In a Gantt chart, a solid bar represents the main task, which is generally composed of a number of subtasks, shown as grey bars. The diamond shape indicates an important deadline/deliverable/milestone.

    W7.6f : OPTIONAL

    Project Management → Project Planning → PERT charts

    Can explain PERT charts

    A PERT (Program Evaluation Review Technique) chart uses a graphical technique to show the order/sequence of tasks. It is based on the simple idea of drawing a directed graph in which:

    • Nodes or vertices capture the effort estimations of tasks, and
    • Arrows depict the precedence between tasks

    An example PERT chart for a simple software project


    md = man days

    A PERT chart can help determine the following important information:

    • The order of tasks. In the example above, Final Testing cannot begin until all coding of individual subsystems have been completed.
    • Which tasks can be done concurrently. In the example above, the various subsystem designs can start independently once the High level design is completed.
    • The shortest possible completion time. In the example above, there is a path (indicated by the shaded boxes) from start to end that determines the shortest possible completion time.
    • The Critical Path. In the example above, the shortest possible path is also the critical path.

    Critical path is the path in which any delay can directly affect the project duration. It is important to ensure tasks on the critical path are completed on time.

    W7.6g

    Project Management → Teamwork → Team structures

    Can explain common team structures

    Given below are three commonly used team structures in software development. Irrespective of the team structure, it is a good practice to assign roles and responsibilities to different team members so that someone is clearly in charge of each aspect of the project. In comparison, the ‘everybody is responsible for everything’ approach can result in more chaos and hence slower progress.

    Egoless team

    In this structure, every team member is equal in terms of responsibility and accountability. When any decision is required, consensus must be reached. This team structure is also known as a democratic team structure. This team structure usually finds a good solution to a relatively hard problem as all team members contribute ideas.

    However, the democratic nature of the team structure bears a higher risk of falling apart due to the absence of an authority figure to manage the team and resolve conflicts.

    Chief programmer team

    Frederick Brooks proposed that software engineers learn from the medical surgical team in an operating room. In such a team, there is always a chief surgeon, assisted by experts in other areas. Similarly, in a chief programmer team structure, there is a single authoritative figure, the chief programmer. Major decisions, e.g. system architecture, are made solely by him/her and obeyed by all other team members. The chief programmer directs and coordinates the effort of other team members. When necessary, the chief will be assisted by domain specialists e.g. business specialists, database experts, network technology experts, etc. This allows individual group members to concentrate solely on the areas in which they have sound knowledge and expertise.

    The success of such a team structure relies heavily on the chief programmer. Not only must he/she be a superb technical hand, he/she also needs good managerial skills. Under a suitably qualified leader, such a team structure is known to produce successful work.

    Strict hierarchy team

    At the opposite extreme of an egoless team, a strict hierarchy team has a strictly defined organization among the team members, reminiscent of the military or a bureaucratic government. Each team member only works on his/her assigned tasks and reports to a single “boss”.

    In a large, resource-intensive, complex project, this could be a good team structure to reduce communication overhead.

    Which team structure is the most suitable for a school project?

    (a)

    Explanation: Given that students are all peers and beginners, the egoless team structure seems most suitable for a school project. However, since school projects are low-stakes, short-lived, and small, even the other two team structures can be used for them.

    Guidance for the item(s) below:

    Continuing on the same theme, given below are more practices used in managing projects, particularly related to the revision control aspect.

    [W7.7] Project Mgt: Workflows

    Video

    W7.7a

    Project Management → Revision Control → Forking flow

    Can explain forking workflow

    In the forking workflow, the 'official' version of the software is kept in a remote repo designated as the 'main repo'. All team members fork the main repo and create pull requests from their fork to the main repo.

    To illustrate how the workflow goes, let’s assume Jean wants to fix a bug in the code. Here are the steps:

    1. Jean creates a separate branch in her local repo and fixes the bug in that branch.
      Common mistake: Doing the proposed changes in the master branch -- if Jean does that, she will not be able to have more than one PR open at any time because any changes to the master branch will be reflected in all open PRs.
    2. Jean pushes the branch to her fork.
    3. Jean creates a pull request from that branch in her fork to the main repo.
    4. Other members review Jean’s pull request.
    5. If reviewers suggested any changes, Jean updates the PR accordingly.
    6. When reviewers are satisfied with the PR, one of the members (usually the team lead or a designated 'maintainer' of the main repo) merges the PR, which brings Jean’s code to the main repo.
    7. Other members, realizing there is new code in the upstream repo, sync their forks with the new upstream repo (i.e. the main repo). This is done by pulling the new code to their own local repo and pushing the updated code to their own fork.
      Possible mistake: Creating another 'reverse' PR from the team repo to the team member's fork to sync the member's fork with the merged code. PRs are meant to go from downstream repos to upstream repos, not in the other direction.

    W7.7b

    Tools → Git and GitHub → Forking workflow

    Can follow Forking Workflow

    You can follow the steps in the simulation of a forking workflow given below to learn how to follow such a workflow.

    This activity is best done as a team.

    Step 1. One member: set up the team org and the team repo.

    1. Create a GitHub organization for your team. The org name is up to you. We'll refer to this organization as team org from now on.

    2. Add a team called developers to your team org.

    3. Add team members to the developers team.

    4. Fork se-edu/samplerepo-workflow-practice to your team org. We'll refer to this as the team repo.

    5. Add the forked repo to the developers team. Give write access.

    Step 2. Each team member: create PRs via own fork.

    1. Fork that repo from your team org to your own GitHub account.

    2. Create a branch named add-{your name}-info (e.g. add-johnTan-info) in the local repo.

    3. Add a file yourName.md into the members directory (e.g., members/jonhTan.md) containing some info about you into that branch.

    4. Push that branch to your fork.

    5. Create a PR from that branch to the master branch of the team repo.

    Step 3. For each PR: review, update, and merge.

    1. [A team member (not the PR author)] Review the PR by adding comments (can be just dummy comments).

    2. [PR author] Update the PR by pushing more commits to it, to simulate updating the PR based on review comments.

    3. [Another team member] Approve and merge the PR using the GitHub interface.

    4. [All members] Sync your local repo (and your fork) with upstream repo. In this case, your upstream repo is the repo in your team org.

    Step 4. Create conflicting PRs.

    1. [One member]: Update README: In the master branch, remove John Doe and Jane Doe from the README.md, commit, and push to the main repo.

    2. [Each team member] Create a PR to add yourself under the Team Members section in the README.md. Use a new branch for the PR e.g., add-johnTan-name.

    Step 5. Merge conflicting PRs one at a time. Before merging a PR, you’ll have to resolve conflicts.

    1. [Optional] A member can inform the PR author (by posting a comment) that there is a conflict in the PR.

    2. [PR author] Resolve the conflict locally:

      1. Pull the master branch from the repo in your team org.
      2. Merge the pulled master branch to your PR branch.
      3. Resolve the merge conflict that crops up during the merge.
      4. Push the updated PR branch to your fork.
    3. [Another member or the PR author]: Merge the de-conflicted PR: When GitHub does not indicate a conflict anymore, you can go ahead and merge the PR.

    W7.7c

    Project Management → Revision Control → DRCS vs CRCS

    Can explain DRCS vs CRCS

    RCS can be done in two ways: the centralized way and the distributed way.

    Centralized RCS (CRCS for short) uses a central remote repo that is shared by the team. Team members download (‘pull’) and upload (‘push’) changes between their own local repositories and the central repository. Older RCS tools such as CVS and SVN support only this model. Note that these older RCS do not support the notion of a local repo either. Instead, they force users to do all the versioning with the remote repo.

    The centralized RCS approach without any local repos (e.g., CVS, SVN)

    Distributed RCS (DRCS for short, also known as Decentralized RCS) allows multiple remote repos and pulling and pushing can be done among them in arbitrary ways. The workflow can vary differently from team to team. For example, every team member can have his/her own remote repository in addition to their own local repository, as shown in the diagram below. Git and Mercurial are some prominent RCS tools that support the distributed approach.

    The decentralized RCS approach

    W7.7d : OPTIONAL

    Project Management → Revision Control → Feature branch flow

    Can explain feature branch flow

    Feature branch workflow is similar to forking workflow except there are no forks. Everyone is pushing/pulling from the same remote repo. The phrase feature branch is used because each new feature (or bug fix, or any other modification) is done in a separate branch and merged to the master branch when ready.

    W7.7e : OPTIONAL

    Project Management → Revision Control → Centralized flow

    Can explain centralized flow

    The centralized workflow is similar to the feature branch workflow except all changes are done in the master branch.