TE3201: SOFTWARE ENGINEERING



Acknowledgements

Using This Book

Browser Compatibility

This book is best viewed using the Chrome browser.

Information Layers

The book tries to layer information so that readers can decide to omit less important layers if they wish to.

More important information are in bold or highlighted while less important information are dimmed or in collapsed panels such as the below.

Less important info

Less important info

Tabs indicate alternative formats of the same content (e.g. video vs text). You can choose the one you like and ignore the other tabs.

Some textual description of X


Video describing X


Dotted underlines indicate tool tips (activated by hovering over it) and dashed underlines indicate modal windows (activated by clicking) containing additional information.

Additional information
Additional information

Sections tagged as can be ignored because they are tangential info that are strictly not within the scope of the topic.

Conventions Used

Meaning of some shortened headings:

  • What : the meaning of the concept in concern

  • Why : the motivation behind the concept in concern

  • How : the usage of the concept in concern

  • When : the pros and cons of the concept in concern, when to use the concept

Boxed-text styles:

additional info warning positive message important message an error to avoid tip definition

Meaning of icons:

  • : indication of the depth of the topic, in order of increasing depth ( is the least depth)
  • : tangential info, can be ignored if not interested
  • : direct link to the LO. Ctrl+Click to open the LO in new window/tab.
  • πŸ† : learning outcomes
  • πŸŽ“ : prerequisite learning outcome
  • πŸ“¦ : examples
  • πŸ“Ž : resources
  • πŸ’ͺ : exercises
  • πŸ“œ : printable version
  • πŸ” : preview/more info
  • πŸ“Ί : video
  • πŸ”€ : textual description
  • πŸ“Š : slides
  • ‡️ : output produced by running code
  • πŸ”’ question without answer
  • πŸ”’πŸ”‘ question with answer

Searching

The book currently does not have a search feature. The workaround is to load the entire book into the web page (i.e. either the full version or the printer-friendly version) and use the Browser's search function.

Saving as PDF Files

  1. Use Chrome to load the page you want to save as pdf.

  2. Click on the Print option in Chrome’s menu.

  3. Set the destination to Save as PDF, then click Save to save a copy of the file in PDF format. For best results, use the settings indicated in the screenshot below.

Printing

A printer-friendly version of the entire book can be found here

SECTION: INTRODUCTION

Software Engineering

Software Engineering β†’

Pros and Cons

Software Engineering: Software Engineering is the application of a systematic, disciplined, quantifiable approach to the development, operation, and maintenance of software" -- IEEE Standard Glossary of Software Engineering Terminology

The following description of the Joys of the Programming Craft was taken from Chapter 1 of the famous book The Mythical Man-Month, by Frederick P. Brooks.

Why is programming fun? What delights may its practitioner expect as his reward?

First is the sheer joy of making things. As the child delights in his mud pie, so the adult enjoys building things, especially things of his own design. I think this delight must be an image of God's delight in making things, a delight shown in the distinctness and newness of each leaf and each snowflake.

Second is the pleasure of making things that are useful to other people. Deep within, we want others to use our work and to find it helpful. In this respect the programming system is not essentially different from the child's first clay pencil holder "for Daddy's office."

Third is the fascination of fashioning complex puzzle-like objects of interlocking moving parts and watching them work in subtle cycles, playing out the consequences of principles built in from the beginning. The programmed computer has all the fascination of the pinball machine or the jukebox mechanism, carried to the ultimate.

Fourth is the joy of always learning, which springs from the nonrepeating nature of the task. In one way or another the problem is ever new, and its solver learns something: sometimes practical, sometimes theoretical, and sometimes both.

Finally, there is the delight of working in such a tractable medium. The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by the exertion of the imagination. Few media of creation are so flexible, so easy to polish and rework, so readily capable of realizing grand conceptual structures....

Yet the program construct, unlike the poet's words, is real in the sense that it moves and works, producing visible outputs separate from the construct itself. It prints results, draws pictures, produces sounds, moves arms. The magic of myth and legend has come true in our time. One types the correct incantation on a keyboard, and a display screen comes to life, showing things that never were nor could be.

Programming then is fun because it gratifies creative longings built deep within us and delights sensibilities we have in common with all men.

Not all is delight, however, and knowing the inherent woes makes it easier to bear them when they appear.

First, one must perform perfectly. The computer resembles the magic of legend in this respect, too. If one character, one pause, of the incantation is not strictly in proper form, the magic doesn't work. Human beings are not accustomed to being perfect, and few areas of human activity demand it. Adjusting to the requirement for perfection is, I think, the most difficult part of learning to program.

Next, other people set one's objectives, provide one's resources, and furnish one's information. One rarely controls the circumstances of his work, or even its goal. In management terms, one's authority is not sufficient for his responsibility. It seems that in all fields, however, the jobs where things get done never have formal authority commensurate with responsibility. In practice, actual (as opposed to formal) authority is acquired from the very momentum of accomplishment.

The dependence upon others has a particular case that is especially painful for the system programmer. He depends upon other people's programs. These are often maldesigned, poorly implemented, incompletely delivered (no source code or test cases), and poorly documented. So he must spend hours studying and fixing things that in an ideal world would be complete, available, and usable.

The next woe is that designing grand concepts is fun; finding nitty little bugs is just work. With any creative activity come dreary hours of tedious, painstaking labor, and programming is no exception.

Next, one finds that debugging has a linear convergence, or worse, where one somehow expects a quadratic sort of approach to the end. So testing drags on and on, the last difficult bugs taking more time to find than the first.

The last woe, and sometimes the last straw, is that the product over which one has labored so long appears to be obsolete upon (or before) completion. Already colleagues and competitors are in hot pursuit of new and better ideas. Already the displacement of one's thought-child is not only conceived, but scheduled.

This always seems worse than it really is. The new and better product is generally not available when one completes his own; it is only talked about. It, too, will require months of development. The real tiger is never a match for the paper one, unless actual use is wanted. Then the virtues of reality have a satisfaction all their own.

Of course the technological base on which one builds is always advancing. As soon as one freezes a design, it becomes obsolete in terms of its concepts. But implementation of real products demands phasing and quantizing. The obsolescence of an implementation must be measured against other existing implementations, not against unrealized concepts. The challenge and the mission are to find real solutions to real problems on actual schedules with available resources.

This then is programming, both a tar pit in which many efforts have floundered and a creative activity with joys and woes all its own. For many, the joys far outweigh the woes....

[Text and book cover source: Wikipedia]

[Fred Brooks photo source]

The Mythical Man-Month: Essays on Software Engineering is a book on software engineering and project management by Fred Brooks, whose central theme is that "adding manpower to a late software project makes it later". This idea is known as Brooks's law, and is presented along with the second-system effect and advocacy of prototyping.

Compare Software Engineering with Civil Engineering in terms of how work products in CE (i.e. buildings) differ from those of SE (i.e. software).

Buildings Software
Visible, tangible Invisible, intangible
Wears out over time Does not wear out
Change is limited by physical restrictions (e.g. difficult to remove a floor from a high rise building) Change is not limited by such restrictions. Just change the code and recompile.
Creating an exact copy of a building is impossible. Creating a near copy is almost as costly as creating the original. Any number of exact copies can be made with near zero cost.
Difficult to move. Easily delivered from one place to another.
Many low-skilled workers following tried-and-tested procedures. No low-skilled workers involved. Workers have more freedom to follow their own procedures.
Easier to assure quality (just follow accepted procedure). Not easy to assure quality.
Majority of the work force has to be on location. Can be built by people who are not even in the same country.
Raw materials are costly, costly equipment required. Almost free raw materials and relatively cheap equipment.
Once construction is started, it is hard to do drastic changes to the design. Building process is very flexible. Drastic design changes can be done, although costly
A lot of manual and menial labor involved. Most work involves highly-skilled labor.
Generally robust. E.g. removing a single brick is unlikely to destroy a building. More fragile than buildings. A single misplaced semicolon can render the whole system useless.

Comment on this statement: Building software is cheaper and easier than building bridges (all we need is a PC!).

Depends on the size of the software. Manpower required for software is very costly. On the other hand, we can create a very valuable software (e.g. an iPhone application that can make million dollars in a month) with a just a PC and a few days of work!

Justify this statement: Coding is still a β€˜design’ activity, not a β€˜manufacturing’ activity. You may use a comparison (or an analogy) of Software engineering versus Civil Engineering to argue this point.

Arguments to support this statement:

  • If coding is a manufacturing activity, we should be able to do it using robotic machines (just like in the car industry) or low-skilled laborers (like in the construction industry).
  • If coding is a manufacturing activity, we wouldn’t be changing it so much after we code software. But if the code is in fact a β€˜design’, yes, we would fiddle with it until we get it right.
  • Manufacturing is the process of building a finished product based on the design. Code is the design. Manufacturing is what is done by the compiler (fully automated).

However, the type of β€˜design’ that occurs during coding is at a much lower level than the β€˜design’ that occurs before coding.

List some (at least three each) pros and cons of Software Engineering compared to other traditional Engineering careers.

  • a. Need for perfection when developing software
  • b. Requiring some amount of tedious, painstaking labor
  • c. Ease of copying and transporting software makes it difficult to keep track of versions
  • d. High dependence on others
  • e. Seemingly never ending effort required for testing and debugging software
  • f. Fast moving industry making our work obsolete quickly

(c)


SECTION: REQUIREMENTS

Requirements

Requirements β†’ Requirements β†’

Introduction

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.

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 should spend extra effort in digging NFRs out as early as possible because NFRs are easier to miss Β e.g., stakeholders tend to think of functional requirements first and sometimes they 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 β†’ Requirements β†’

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.

Requirements β†’ Requirements β†’

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

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 β†’ Gathering Requirements β†’

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.

Requirements β†’ Gathering Requirements β†’

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.

Requirements β†’ Gathering Requirements β†’

Interviews

Interviewing stakeholders and domain experts can give us 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.

Requirements β†’ Gathering Requirements β†’

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.

Requirements β†’ Gathering Requirements β†’

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.

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.

Specifying Requirements

Prose

Requirements β†’ Specifying Requirements β†’ Prose β†’

What

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

Feature List

Requirements β†’ Specifying Requirements β†’ Feature Lists β†’

What

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

User Stories

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.

Requirements β†’ Specifying Requirements β†’ User Stories β†’

Details

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, we could end up adding features that have no real benefit.

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

We can write user stories at various levels. High-level user stories, called epics (or themes) cover bigger functionality. We 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

We 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

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.

Requirements β†’ Specifying Requirements β†’ User Stories β†’

Usage

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.

πŸ“¦ 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 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.

Use Cases

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 β†’ Specifying Requirements β†’ Use Cases β†’

Identifying

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.

Requirements β†’ Specifying Requirements β†’ Use Cases β†’

Details

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.

❌ User right-clicks the text box and chooses β€˜clear’ Β : this contains UI-specific details and is not a good use case step)

βœ… User clears the input Β : this is better because it omits UI-specific details

This is how you can include repetitive steps in a scenario.

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

Requirements β†’ Specifying Requirements β†’ Use Cases β†’

Usage

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.

Glossary

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.

Supplementary Requirements

Requirements β†’ Specifying Requirements β†’ Supplementary Requirements β†’

What

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 should spend extra effort in digging NFRs out as early as possible because NFRs are easier to miss Β e.g., stakeholders tend to think of functional requirements first and sometimes they 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.


SECTION: DESIGN

Design

Introduction

Design β†’ Introduction β†’

What

Design in 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 the 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.

Object-Oriented Programming

Introduction

Design β†’ Object Oriented Programming β†’

Introduction

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.

Objects

Design β†’ Object Oriented Programming β†’ Objects β†’

Basic

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 to achieve 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 and 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 Text Book (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.

Design β†’ Object Oriented Programming β†’ Objects β†’

Objects as Abstractions

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 data formats and the method implementation details and work at the level of objects.

πŸ“¦ 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.

Design β†’ Object Oriented Programming β†’ Objects β†’

Encapsulation Of Objects

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 statement

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

Classes

Design β†’ Object Oriented Programming β†’ Classes β†’

Basic

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 in one go and use that same instructions to instantiate (i.e. create) objects of that kind. We call such instructions a Class.

πŸ“¦ Classes and objects in an example scenario

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

Let us use the UML notation to illustrate classes and objects under discussion.

Person class and some example instances of the Person class.

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

John gave a checque to the Cashier pay for the LoTR and GoT books he bought.
Class Objects
Customer John
Book LoTR GoT
Cheque checqueJohnGave
Cashier bookshopCashier

Implementation β†’ Object Oriented Programming β†’

Implementing Classes

Given below is a tutorial you can refer to (from Oracle’s official Java tutorials) to learn how to implement java classes, in the unlikely case you don't know how to do that already.

Design β†’ Object Oriented Programming β†’ Classes β†’

Class Level Members

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

Example:

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.

Example:

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.

Example:

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.

Example:

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.

πŸ“¦ A Student class with a class-level attribute and a method:

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.

Implementation β†’ Object Oriented Programming β†’

Implementing Class-Level Members

You can refer to Oracle’s official Java tutorial on class-level members to learn how to implement Java class-level members, in the unlikely case you don't know how to do that already.

Associations

Design β†’ Object Oriented Programming β†’ Associations β†’

Basic

Objects in an OO solution need to be connected to each other to form a network so that they can interact with each other. Such connections between objects are called associations.

πŸ“¦ An object diagram example showing associations among objects. For example, there is an association between the AgeList object and the Main object.

Associations in an object structure can change over time.

πŸ“¦ In this example, the associations in the object structure have changed (from left to right) due to a new Person object being connected to the Main object.

Β  β†’

Associations among objects are reflected correspondingly in the class diagram too, as it is the class diagram that dictates the nature of the associations allowed in the object structures.

πŸ“¦ An example class diagram showing associations between classes.

Design β†’ Object Oriented Programming β†’ Associations β†’

When two classes are linked by an association, it does not necessarily mean both classes know about each other. The concept of which class in the association knows about the other class is called navigability.

(a)

Explanation: The diagram indicates that Unit object should know about the Item object. In the implementation, the Unit object will hold a Unit object in one of its variables.

Design β†’ Object Oriented Programming β†’ Associations β†’

Multiplicity

Multiplicity is the aspect of an OOP solution that dictates how many objects take part in each association.

πŸ“¦ This class diagram does not tell us multiplicities. For exaple, how many Calculator objects can be associated with one Main object? How many Main objects can be associated with one Calculator object? and so on.

  • a. A Unit object can be linked to any number of Item objects
  • b. An Item object must be linked 1,2,3 or 4 Unit objects.
  • c. A Unit object must be linked 1,2,3, or 4 Item objects
  • d. A Item object can be 0 or more Unit objects.

(c)(d)

Implementation β†’ Object Oriented Programming β†’

Implementing Associations

We use instance level variables to implement associations.

A normal instance-level variable gives us a 0..1 multiplicity (also called optional associations) because a variable can hold a reference to a single object or null.

class Logic {
    Minefield minefield;
    ...
}
class Minefield {
    ...
}

A variable can be used to implement a 1 multiplicity too (also called compulsory associations).

class Logic {
    ConfigGenerator cg = new ConfigGenerator();
    ...
}

Bi-directional associations require matching variables in both classes.

class Foo {
    Bar bar;
    ...
}
class Bar {
    Foo foo;
    ...
}

To implement other multiplicities, choose a suitable data structure such as Arrays, ArrayLists, HashMaps, Sets, etc.

class Minefield {
    Cell[][] cell;
    ...
}

Draw a class diagram for the code below. Also draw an object diagram that will represent the object structure after running Main#main().

  • Make the multiplicities as strict as possible without contradicting the code.
  • You may omit the Main class from both diagrams.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        Item item1 = new Item();
        Item item2 = new Item();
        Box box1 = new Box(item1);
        Box box2 = new Box(item2);
        item2.setMainCard(new Card());
        item2.addPreviousBox(box1);
        item2.addPreviousBox(box2);
    }
}

class Box{
    private Item item;
    Box (Item item){
        this.item = item;
    }
}

class Item{
    private List<Box> previousBoxes = new ArrayList<>();
    private Card mainCard = null;
    private Card subCard = null;

    void setMainCard(Card card){
        this.mainCard = card;
    }
    
    void setSubCard(Card card){
        this.subCard = card;
    }

    void addPreviousBox(Box previousBox){
        previousBoxes.add(previousBox);
    }
}

class Card{
    
}

Suppose we wrote a program to follow the class structure given in this class diagram:

Draw object diagrams to represent the object structures after each of these steps below. Assume that we are trying to minimize the number of total objects.

i.e. apply step 1 β†’ [diagram 1] β†’ apply step 2 on diagarm 1 β†’ [diagarm 2] and so on.

  1. There are no persons.

  2. Alfred is the Guardian of Bruce.

  3. Bruce's contact number is the same as Alfred's.

  4. Alfred is also the guardian of another person. That person lists Alfreds home address as his home address as well as office address.

  5. Alfred has a an office address at Wayne Industries building which is different from his home address (i.e. Bat Cave).

After step 2, the diagram should be like this:

Implement the class structure given below:

Design β†’ Object Oriented Programming β†’

Dependencies

Dependencies are objects that are not directly linked in the object network can still interact with each other. These are a weaker form of associations we call dependencies.

Implementation β†’ Object Oriented Programming β†’

Implementing Dependencies

Dependencies result from interactions between objects that do not result in a long-term link between the said objects.

Example:

class TaxProcessor{
    double rate;

    void addTax(Taxable t){
        t.addTax(rate);
    }
}

The code above results in this dependency.

The code does not indicate an association between the two classes because the TaxProcessor object does not keep the Taxable object (i.e. it’s only a short-term interaction)

Design β†’ Object Oriented Programming β†’ Associations β†’

Composition

A composition is an association that represents a strong whole-part relationship. When the whole is destroyed, parts are destroyed too.

πŸ“¦ A Board (used for playing board games) consists of Square objects.

Composition also implies that there cannot be cyclical links.

πŸ“¦ In this β€˜sub-folder’ association, a Folder cannot be a sub-folder of itself. If the diamond is removed, it is no longer a composition relationship and technically, allows a folder to be sub-folder of itself.

Implementation β†’ Object Oriented Programming β†’

Implementing Composition

Composition too is implemented using a normal variable. If correctly implemented, the β€˜part’ object will be deleted when the β€˜whole’ object is deleted. Ideally, the β€˜part’ object may not even be visible to clients of the β€˜whole’ object.

Example:

class Car {
    private Engine engine;
  ...
}

Design β†’ Object Oriented Programming β†’ Associations β†’

Aggregation

Aggregation represents a container-contained relationship. It is a weaker relationship than composition.

πŸ“¦ Club acts as a container for Person objects. Person objects can survive without a Club object.

Aggregation vs Composition

The distinction between composition (β—†) and aggregation (β—‡) is rather blurred. Martin Fowler’s famous book UML Distilled advocates omitting the aggregation symbol altogether because using it adds more confusion than clarity.

Which one of these is recommended not to use in UML diagrams because it adds more confusion than clarity?

(b)

Implementation β†’ Object Oriented Programming β†’

Implementing Aggregation

Implementation is similar to that of composition except the containee object can exist even after the container object is deleted.

πŸ“¦ Example:

class Car {
    Person driver;
    ...
    void drive(Person p) {
        driver = p;
    }
}

Inheritance

Design β†’ Object Oriented Programming β†’ Inheritance β†’

What

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.

πŸ“¦ Example: The EvaluationReport inherits 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 super class is said to be more general than the sub class. Conversely, a sub class is said to be more specialized than the super class.

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 the 'owes money' association. 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 the β€˜marriage’ association. A solution is to add the Person class as a super class and let Man and Woman inherit from Person.

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.

πŸ“¦ In this class diagrams of a Snakes and Ladders board game,

  • SnakeHeadSquare is a Square Β (a SnakeHeadSquare is a square in which the head of a snake appears)
  • SnakeTailSquare is a Square

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

πŸ“¦ Two inheritance hierarchies/trees are given below. Note that Parrot is a Bird as well as it is an Animal.

Multiple Inheritance is when a class inherits directly from multiple classes. Multiple inheritance is allowed among C++ classes but not among Java classes.

πŸ“¦ The TA class inherits from the Staff class and the Student.

Implementation β†’ Object Oriented Programming β†’

Implementing Inheritance

To learn how to implement inheritance in Java, you can follow [Oracle’s Java Tutorials: Inheritance]


A very beginner-friendly video about implementing Java inheritance.


Java requires all class to have a parent class. If you do not specify a parent class, Java automatically assigns the Object class as the parent class.

Design β†’ Object Oriented Programming β†’ Inheritance β†’

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.

πŸ“¦ In the diagram below,

  • Report#print() method is overridden by EvaluationReport#print() method.
  • Report#write(String) method is overridden by EvaluationReport#write(String) method.
  • Report#read():String method is NOT overridden by EvaluationReport#read(int):String method. Β Reason: the two methods have different signatures; EvaluationReport#read(int):String overloads (rather than overrides) the Report#read():String method.

Design β†’ Object Oriented Programming β†’

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 class below, the calculate method is overloaded because the two methods have the same name but different type signatures (String) and (int[])

class RatingCalculator{
    void calculate(String matric) { ... }
    void calculate(int[] averages) { ... }
}

Implementation β†’ Object Oriented Programming β†’

Implementing Overriding

To override a method inherited from an ancestor class, simply re-implement the method in the target class.

πŸ“¦ A simple example where the Report#print() method is overridden by EvaluationReport#print() method:


class Report{

    void print(){
        System.out.println("Printing report");
    }

}

class EvaluationReport extends Report{

    @Override  // this annotation is optional
    void print(){
        System.out.println("Printing evaluation report");
    }

}

class ReportMain{

    public static void main(String[] args){
        Report report = new Report();
        report.print(); // prints "Printing report"

        EvaluationReport evaluationReport = new EvaluationReport();
        evaluationReport.print(); // prints "Printing evaluation report"
    }
}

Which of these methods override another method?

  • 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

Design β†’ Object Oriented Programming β†’

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 class below, the calculate method is overloaded because the two methods have the same name but different type signatures (String) and (int[])

class RatingCalculator{
    void calculate(String matric) { ... }
    void calculate(int[] averages) { ... }
}

Implementation β†’ Object Oriented Programming β†’

Implementing Overloading

An operation can be overloaded inside the same class or in sub/super classes.

πŸ“¦ The constructor of the Account class below is overloaded because there are two constructors with different signatures: () and (String, String, double). Furthermore, the save method in the Account class is overloaded in the child class SavingAccount.

class Account {
    Account () {
        ...
    }
    
    Account (String name, String number, double balance) {
        ...
    }
    
    void save(int amount){
        ...
    }
}

class SavingAccount extends Account{
    
    void save(Double amount){
        ...
    }
}

Design Fundamentals

Abstraction

Design β†’ Design Fundamentals β†’ Abstraction β†’

What

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

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. The guiding principle of abstraction stipulates that we capture only details that are relevant to the current perspective or the task at hand.

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.

For example,

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.

Modeling

Introduction

Design β†’ Modelling β†’ Introduction β†’

What

A model is a representation of something else.

πŸ“¦ A class diagram is a model that represents a software design.

A class diagram is a diagram drawn using the UML modelling notation.
πŸ“¦ An example class diagram:

A model provides a simpler view of a complex entity because a model captures only a selected aspect. This omission of some aspects implies models are abstractions.

Design β†’ Design Fundamentals β†’ Abstraction β†’

What

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

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. The guiding principle of abstraction stipulates that we capture only details that are relevant to the current perspective or the task at hand.

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.

For example,

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.

πŸ“¦ A class diagram captures the structure of the software design but not the behavior.

Multiple models of the same entity may be needed to capture it fully.

πŸ“¦ In addition to a class diagram (or even multiple class diagrams), a number of other diagrams may be needed to capture various interesting aspects of the software.

Design β†’ Modelling β†’ Introduction β†’

How

In software development, models are useful in several ways:

a) To analyze a complex entity related to software development.

πŸ“¦ Some examples of using models for analysis:

  1. Models of the problem domain (i.e. the environment in which the software is expected to solve a problem) can be built to aid the understanding of the problem to be solved.
  2. When planning a software solution, models can be created to figure out how the solution is to be built. An architecture diagram is such a model.

b) To communicate information among stakeholders. Models can be used as a visual aid in discussions and documentations.

πŸ“¦ Some examples of using models to communicate:

  1. An architect can use an architecture diagram to explain the high-level design of the software to developers.
  2. A business analyst can use a use case diagram to explain to the customer the functionality of the system.
  3. A class diagram can be reverse-engineered from code so as to help explain the design of a component to a new developer.

c) As a blueprint for creating software. Models can be used as instructions for building software.

πŸ“¦ Some examples of using models to as blueprints:

  1. A senior developer draws a class diagram to propose a design for an OOP software and passes it to a junior programmer to implement.
  2. A software tool allows users to draw UML models using its interface and the tool automatically generates the code based on the model.

Model-driven development (MDD), also called Model-driven engineering, is an approach to software development that strives to exploits models as blueprints. MDD uses models as primary engineering artifacts when developing software. That is, the system is first created in the form of models. After that, the models are converted to code using code-generation techniques (usually, automated or semi-automated, but can even involve manual translation from model to code). MDD requires the use of a very expressive modeling notation (graphical or otherwise), often specific to a given problem domain. It also requires sophisticated tools to generate code from models and maintain the link between models and the code. One advantage of MDD is that the same model can be used to create software for different platforms and different languages. MDD has a lot of promise, but it is still an emerging technology

Further reading:

Choose the correct statements about models.

  • a. Models are abstractions.
  • b. Models can be used for communication.
  • c. Models can be used for analysis of a problem.
  • d. Generating models from code is useless.
  • e. Models can be used as blueprints for generating code.

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

Explanation: Models generated from code can be used for understanding, analysing, and communicating about the code.

Explain how models (e.g. UML diagrams) can be used in a class project.

Can models be useful in evaluating the design quality of a software written by students?

Design β†’ Modelling β†’ Introduction β†’

UML Models

The following diagram uses the class diagram notation to show the different types of UML diagrams.


source:https://en.wikipedia.org/

Modeling Structures

Design β†’ Modelling β†’ Modelling Structure

Class Diagrams (Basics)

Associations among objects/classes play an important role in an OO solution.

The most basic class diagram is a bunch of classes with some solid lines among them to represent associations, such as this one.

πŸ“¦ An example class diagram showing associations between classes.

In addition, associations can show additional decorations such as association labels, association roles, multiplicity and navigability to add more information to a class diagram.

πŸ“¦ Here is the same class diagram shown earlier but with some additional information included:

Which association notatations are shown in this diagram?

  • a. association labels
  • b. association roles
  • c. association multiplicity
  • d. class names

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

Explanation: '1’ is a multiplicity, β€˜mentored by’ is a label, and β€˜mentor’ is a role.

Explain the associations, navigabilities, and multiplicities in the class diagram below:

Design β†’ Modeling β†’

Object Diagrams

An object diagram shows an object structure at a given point of time.

Design β†’ Modelling β†’ Modelling Structure

Object Oriented Domain Models

The analysis process for identifying objects and object classes is recognized as one of the most difficult areas of object-oriented development. --Ian Sommerville, in the book Software Engineering

Class diagrams can also be used to model objects in the problem domain (i.e. to model how objects actually interact in the real world, before emulating them in the solution). Class diagrams are used to model the problem domain are called conceptual class diagrams or OO domain models (OODMs).

πŸ“¦ OO domain model of a snakes and ladders game is given below.

Description: Snakes and ladders game is played by two or more players using a board and a die. The board has 100 squares marked 1 to 100. Each player owns one piece. Players take turns to throw the die and advance their piece by the number of squares they earned from the die throw. The board has a number of snakes. If a player’s piece lands on a square with a snake head, the piece is automatically moved to the square containing the snake’s tail. Similarly, a piece can automatically move from a ladder foot to the ladder top. The player whose piece is the first to reach the 100th square wins.

The above OO domain model omits the ladder class for simplicity. It can be included in a similar fashion to the Snake class.

OODMs do not contain solution-specific classes (i.e. classes that are used in the solution domain but do not exist in the problem domain). For example, a class called DatabaseConnection could appear in a class diagram but not usually in an OO domain model because DatabaseConnection is something related to a software solution but not an entity in the problem domain.

OODMs represents the class structure of the problem domain and not their behavior, just like class diagrams. To show behavior, use other diagrams such as sequence diagrams.

OODM notation is similar to class diagram notation but typically omit methods and navigability.

This diagram is,

  • a. A class diagram.
  • b. An object diagram.
  • c. An OO domain model, also known as a conceptual class diagram.
  • d. Can be either a class diagram or an OO domain model.

(a)

Explanation: The diagram shows navigability which is not shown in an OO domain model. Hence, it has to be a class diagram.

What is the main difference between a class diagram and and an OO domain model?

(a)

Explanation: Both are UML diagrams, and use the class diagram notation. While it is true that often a class diagram may have more classes and more details, the main difference is that the OO domain model describes the problem domain while the class diagram describes the solution.

Modeling Behaviors

Design β†’ Modeling β†’

Activity Diagrams

Software projects often involve workflows. Workflows define the flow in which a process or a set of tasks is executed.

Some examples in which a certain workflow is relevant to software project:

πŸ“¦ A software that automates the work of an insurance company needs to take into account the workflow of processing an insurance claim.

πŸ“¦ The algorithm of a price of code represents the workflow (i.e. the execution flow) of the code.

Understanding such workflows is important for the success of the software project. UML Β activity diagrams (AD) can model workflows.Β  Flow charts is another type of diagrams that can model workflows. Activity diagrams are the UML equivalent of flow charts.

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.

πŸ“¦ An example activity diagram [source:wikipeida]:

The most basic activity diagram is simply a linear sequence of actions.

Some workflows have alternate paths where only one of the alternate paths is taken based on some condition.

In some workflows, multiple paths happen in parallel.

Which of these sequence of actions is not allowed by the given activity diagram?

  • i. start a b c d end
  • ii. start a b c d e f g c d end
  • iii. start a b c d e g f c d end
  • iv. start a b c d g c d end

(iv)

Explanation: -e-f- and -g- are parallel paths. Both paths should complete before the execution reaches c again.

Design β†’ Modeling β†’

Use Case Diagrams

Use case diagrams model the mapping between features of a system and its user roles.

πŸ“¦ A simple use case diagram:


SECTION: IMPLEMENTATION

Error Handling

Introduction

Implementation β†’ Error Handling β†’ Introduction β†’

What

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. --(source)

Exceptions

Implementation β†’ Error Handling β†’ Exceptions β†’

What

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

Exception:

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.

Implementation β†’ Error Handling β†’ Exceptions β†’

How

Most languages allow a method to encapsulate the unusual 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 code segment that encountered the unusual situation does not know how to deal with it.

Exception objects can propagate up the method/function call hierarchy until it is dealt with. Usually, an exception thrown by a method is caught by the caller method. If the called method does not know how to deal with the exception it caught, it can throw/raise the Exception object to its own caller. If none of the callers is prepared to deal with the exception, the exceptions can propagate through the method call stack until it is received by the main method and thrown to the runtime, thus halting the system.

πŸ“¦ In the code given below, processArray can potentially throw an InvalidInputException. Because of that, processInput method invokes processArray method inside a try{ } block and has a catch{ } block to specify what to do if the exception is actually thrown.

πŸ“¦ In the code given below, process_array function can potentially raise a ValueError exception. Because of that, process_input function invokes process_array function inside a try clause and has a except clause to specify what to do if the exception is actually raised.


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.

Implementation β†’ Error Handling β†’ Exceptions β†’

When

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

IDEs

Introduction

IDEs β†’ Introduction β†’

What

Professional software engineers often write code using Integrated Development Environments (IDEs). IDEs support all development-related work within the same tool.

An IDE generally consists of:

  • A source code editor that includes features such as syntax coloring, auto-completion, easy code navigation, error highlighting, and code-snippet generation.
  • A compiler and/or an interpreter (together with other build automation support) that facilitates the compilation/linking/running/deployment of a program.
  • A debugger that allows the developer to execute the program one step at a time to observe the run-time behavior in order to locate bugs.
  • Other tools that aid various aspects of coding e.g. support for automated testing, drag-and-drop construction of UI components, version management support, simulation of the target runtime platform, and modeling support.

Examples of popular IDEs:

  • Java: Eclipse, Intellij IDEA, NetBeans
  • C#, C++: Visual Studio
  • Swift: XCode
  • Python: PyCharm

Some Web-based IDEs have appeared in recent times too e.g., Amazon's Cloud9 IDE.

Some experienced developers, in particular those with a UNIX background, prefer lightweight yet powerful text editors with scripting capabilities (e.g. Emacs) over heavier IDEs.

  • a. Compiling.
  • b. Syntax error highlighting.
  • c. Debugging.
  • d. Code navigation e.g., to navigate from a method call to the method implementation.
  • e. Simulation e.g., run a mobile app in a simulator.
  • f. Code analysis e.g. to find unreachable code.
  • g. Reverse engineering design/documentation e.g. generate diagrams from code
  • h. Visual programming e.g. Write programs using β€˜drag and drop’ actions instead of typing code.
  • i. Syntax assistance e.g., show hints as you type.
  • j. Code generation e.g., to generate the code required by simply specifying which component/structure you want to implement.
  • k. Extension. i.e. ability add more functionality to the IDE using plugins.

All.

Explanation: While all of these features may not be present in some IDEs, most do have these features in some form or other.

Debugging

Implementation β†’ IDEs β†’ Debugging β†’

What

Debugging is the process of discovering defects in the program. Here are some approaches to debugging:

  • πŸ‘Ž By inserting temporary print statements: This is an ad-hoc approach in which print statements are inserted in the program to print information relevant to debugging, such as variable values. e.g. Exiting process() method, x is 5.347. This approach is not recommended due to these reasons.

    • Incurs extra effort when inserting and removing the print statements.
    • Unnecessary program modifications increases the risk of introducing errors into the program.
    • These print statements, if not promptly removed, may even appear unexpectedly in the production version.
  • πŸ‘Ž By manually tracing through the code: Otherwise known as β€˜eye-balling’, this approach doesn't have the cons of the previous approach, but it too is not recommended (other than as a 'quick try') due to these reasons:

    • It is difficult, time consuming, and error-prone technique.
    • If you didn't spot the error while writing code, you might not spot the error when reading code too.
  • πŸ‘ Using a debugger: A debugger tool allows you to pause the execution, then step through one statement at a time while examining the internal state if necessary. Most IDEs come with an inbuilt debugger. This is the recommended approach for debugging.

Code Quality

Introduction

Implementation β†’ Code Quality β†’ Introduction β†’

Basic

Always code as if the person who ends up maintaining your code will be a violent psychopath who knows where you live. -- Martin Golding

Production code needs to be of high quality. Given how the world is becoming increasingly dependent of software, poor quality code is something we cannot afford to tolerate.

Code being used in an actual product with actual users

Guideline: Maximise Readability

Implementation β†’ Code Quality β†’ Readability β†’

Introduction

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.

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

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

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;
}

Implementation β†’ Code Quality β†’ Readability β†’

Basic

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.

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:

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:

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


boolean isWithinSizeLimit = length < MAX_LENGTH;
boolean isSameSize = previousSize != length;
boolean isValidCode = isWithinSizeLimit || isSameSize;

boolean isUrgent = typeCode == URGENT;

return isValidCode && isUrgent;

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

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

Example:

return 3.14236; return PI
return 9 return MAX_SIZE-1

Using a named constant makes the code easier to understand because the name tells us more about the meaning of the number. Similarly, we can have β€˜magic’ values of other data types.

return β€œError 1432”;  // A magic string!

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

  • Use explicit type conversion instead of implicit type conversion.
  • Use parentheses/braces to show grouping even when they can be skipped.
  • 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'.
  • When statements should follow a particular order, try to make it obvious (with appropriate naming, or at least comments). For example, if you name two functions 'taskA()' and 'taskB()', it is not obvious which one should be called first. Contrast this with naming the functions 'phaseOne()' and 'phaseTwo()' instead. This is especially important when statements in one function must be called before the other one.

Guideline: Follow a Standard

Implementation β†’ Code Quality β†’ Style β†’

Introduction

One essential way to improve code quality is to follow a consistent style. That is why software engineers follow a strict coding standard (aka style guide).

The aim of a coding standard is to make the entire code base look like it was written by one person. A coding standard is usually specific to a programming language and specifies guidelines such as the location of opening and closing braces, indentation styles and naming styles (e.g. whether to use Hungarian style, Pascal casing, Camel casing, etc.). It is important that the whole team/company use the same coding standard and that standard is not generally inconsistent with typical industry practices. If a company's coding standards is very different from what is used typically in the industry, new recruits will take longer to get used to the company's coding style.

IDEs can help to enforce some parts of a coding standard e.g. indentation rules.

What is the recommended approach regarding coding standards?

c

What is the aim of using a coding standard? How does it help?

Implementation β†’ Code Quality β†’ Style β†’

Basic

Go through the provided Java coding standard and learn the basic style rules.

Guideline: Name Well

Implementation β†’ Code Quality β†’ Naming β†’

Introduction

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

Implementation β†’ Code Quality β†’ Naming β†’

Basic

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

Examples:

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

Distinguish clearly between single valued and multivalued variables.

Examples:

Person student
ArrayList<Person> students

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

Guideline: Comment Minimally, But Sufficiently

Implementation β†’ Code Quality β†’ Comments β†’

Introduction

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.

Implementation β†’ Code Quality β†’ Comments β†’

Basic

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

// increment x
x++;

//trim the input
trimInput();

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.

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(){
    ....
}

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

Refactoring

Implementation β†’ Refactoring β†’

What

The first version of the code you write may not be of production quality. It is OK to first concentrate on making the code work, rather than worry over the quality of the code, as long as you improve the quality later. This process of improving a program's internal structure in small steps without modifying its external behavior is called refactoring.

  • Refactoring is not rewriting: Discarding poorly-written code entirely and re-writing it from scratch is not refactoring because refactoring needs to be done in small steps.
  • Refactoring is not bug fixing: By definition, refactoring is different from bug fixing or any other modifications that alter the external behavior (e.g. adding a feature) of the component in concern.

πŸ’‘ Improving code structure can have many secondary benefits: e.g.

  • hidden bugs become easier to spot
  • improve performance (sometimes, simpler code runs faster than complex code because simpler code is easier for the compiler to optimize).

Given below are two common refactorings (taken from refactoring-catalog ).

http://refactoring.com/catalog/ - This is a list of common refactorings, maintained by Martin Fowler, a leading authority on refactoring. He is also the author of the β€˜bestseller’ on refactoring: Refactoring: Improving the Design of Existing Code

Refactoring Name: Consolidate Duplicate Conditional Fragments

Situation: The same fragment of code is in all branches of a conditional expression.

Method: Move it outside of the expression.

Example:

if (isSpecialDeal()) {
    total = price * 0.95;
    send();
} else {
    total = price * 0.98;
    send();
}

‡️

if (isSpecialDeal()){
    total = price * 0.95;
} else {
    total = price * 0.98;
}
send();

Refactoring Name: Extract Method

Situation: You have a code fragment that can be grouped together.

Method: Turn the fragment into a method whose name explains the purpose of the method.

Example:

void printOwing() {
    printBanner();

    //print details
    System.out.println("name:	" + name);
    System.out.println("amount	" + getOutstanding());
}

‡️

void printOwing() {
    printBanner();
    printDetails(getOutstanding());
}

void printDetails (double outstanding) {
    System.out.println("name:	" + name);
    System.out.println("amount	" + outstanding);
}

πŸ’‘ Some IDEs have built in support for basic refactorings such as automatically renaming a variable/method/class in all places it has been used.

Important: Refactoring, even if done with the aid of an IDE, may still result in regressions. Therefore, each small refactoring should be followed by regression testing.

Choose the correct statements

  • a. Refactoring can improve understandability
  • b. Refactoring can uncover bugs
  • c. Refactoring can result in better performance
  • d. Refactoring can change the number of methods/classes

a, b, c, d

Explanation:

  • (a, b, c) Although the primary aim of refactoring is to improve internal code structure, there are other secondary benefits.
  • (d) Some refactorings result in adding/removing methods/classes.

Do you agree with the following statement? Justify your answer.

Statement: Whenever we refactor code to fix bugs, we need not do regression testing if the bug fix was minor.

There are two flaws in the given statement.

DISAGREE.

  1. Even a minor change can have major repercussions on the system. We MUST do regression testing after each change, no matter how minor it is.
  2. Fixing bugs is technically not refactoring.

Explain what is refactoring and why it is not the same as rewriting, bug fixing, or adding features.

Reuse

Introduction

Implementation β†’ Reuse β†’ Introduction β†’

What

Reuse is a major theme in software engineering practices. By reusing tried-and-tested components, the robustness of a new software system can be enhanced while reducing the manpower and time requirement. Reusable components come in many forms; it can be reusing a piece of code, a subsystem, or a whole software.

Implementation β†’ Reuse β†’ Introduction β†’

When

While you may be tempted to use many libraries/frameworks/platform that seem to crop up on a regular basis and promise to bring great benefits, note that there are costs associated with reuse. Here are some:

  • The reused code may be an overkill (think using a sledgehammer to crack a nut) increasing the size of, or/and degrading the performance of, your software.
  • The reused software may not be mature/stable enough to be used in an important product. That means the software can change drastically and rapidly, possibly in ways that break your software.
  • Non-mature software has the risk of dying off as fast as they emerged, leaving you with a dependency that is no longer maintained.
  • The license of the reused software (or its dependencies) restrict how you can use/develop your software.
  • The reused software might have bugs, missing features, or security vulnerabilities that are important to your product but not so important to the maintainers of that software, which means those flaws will not get fixed as fast as you need them to.
  • Malicious code can sneak into your product via compromised dependencies.

One of your teammates is proposing to use a recently-released β€œcool” UI framework for your class project. List the pros and cons of this idea.

Pros

  • The potential to create a much better product by reusing the framework.
  • Learning a new framework is good for the future job prospects.

Cons

  • Learning curve may be steep.
  • May not be stable (it was recently released).
  • May not allow us to do exactly what we want. While frameworks allow customization, such customization can be limited.
  • Performance penalties.
  • Might interfere with learning objectives of the module.

Note that having more cons does not mean we should not use this framework. Further investigation is required before we can make a final decision.

APIs

Implementation β†’ Reuse β†’ APIs β†’

What

An Application Programming Interface (API) specifies the interface through which other programs can interact with a software component. It is a contract between the component and its clients.

πŸ“¦ The API of the Java String class is a collection of public methods that you can invoke to make use of the String class.

πŸ“¦ The GitHub API is a collection of Web request formats GitHub server accepts and the corresponding responses. We can write a program that interacts with GitHub through that API.

When developing large systems, if you define the API of each components early, the development team can develop the components in parallel Β because the future behavior of the other components are now more predictable.

Choose the correct statements

  • a. A software component can have an API.
  • b. Any method of a class is part of its API.
  • c. Private methods of a class are not part of its API.
  • d. The API forms the contract between the component developer and the component user.
  • e. Sequence diagrams can be used to show how components interact with each other via APIs.

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

Explanation: (b) is incorrect because private methods cannot be a part of the API

Defining component APIs early is useful for developing components in parallel.

True

Explanation: Yes, once we know the precise behavior expected of each component, we can start developing them in parallel.

Libraries

Implementation β†’ Reuse β†’ Libraries β†’

What

A library is a collection of modular code that is general and can be used by other programs.

πŸ“¦ Java classes you get with the JDK (such as String, ArrayList, HashMap, etc.) are library classes that are provided in the default Java distribution.

πŸ“¦ Natty is a Java library that can be used for parsing strings that represent dates e.g. The 31st of April in the year 2008

Implementation β†’ Reuse β†’ Libraries β†’

How

These are the typical steps required to use a library.

  1. Read the documentation to confirm that its functionality fits your needs
  2. Check the license to confirm that it allows reuse in the way you plan to reuse it. For example, some libraries might allow non-commercial use only.
  3. Download the library and make it accessible to your project. Alternatively, you can configure your dependency management tool to do it for you.
  4. Call the library API from your code where you need to use the library functionality.

Frameworks

Implementation β†’ Reuse β†’ Frameworks β†’

What

The overall structure and execution flow of a specific category of software systems can be very similar. The similarity is an opportunity to reuse at a high scale.

πŸ“¦ Running example:

IDEs for different programming languages are similar in how they support editing code, organizing project files, debugging, etc.

A software framework is a reusable implementation of a software (or part thereof) providing generic functionality that can be selectively customized to produce a specific application.

πŸ“¦ Running example:

Eclipse is an IDE framework that can be used to create IDEs for different programming languages.

Some frameworks provide a complete implementation of a default behavior which makes them immediately usable.

πŸ“¦ Running example:

Eclipse is a fully functional Java IDE out-of-the-box.

A framework facilitates the adaptation and customization of some desired functionality.

πŸ“¦ Running example:

Eclipse plugin system can be used to create an IDE for different programming languages while reusing most of the existing IDE features of Eclipse. E.g. https://marketplace.eclipse.org/content/pydev-python-ide-eclipse

Some frameworks cover only a specific components or an aspect.

πŸ“¦ JavaFx a framework for creating Java GUIs.

πŸ“¦ More examples of frameworks

  • Drupal: a framework for Web-based applications, content management systems in particular. Implemented using PHP
  • Ruby on Rails : another Web-application framework similar to Drupal but uses Ruby instead of PHP
  • JUnit: a framework for testing Java code.

Implementation β†’ Reuse β†’ Frameworks β†’

Frameworks vs Libraries

Although both frameworks and libraries are reuse mechanisms, there are notable differences:

  • Libraries are meant to be used β€˜as is’ while frameworks are meant to be customized/extended. Β e.g., writing plugins for Eclipse so that it can be used as an IDE for different languages (C++, PHP, etc.), adding modules and themes to Drupal, and adding test cases to JUnit.

  • Your code calls the library code while the framework code calls your code. Frameworks use a technique called inversion of control, aka the β€œHollywood principle” (i.e. don’t call us, we’ll call you!). That is, you write code that will be called by the framework, Β e.g. writing test methods that will be called by the JUnit framework. In the case of libraries, your code calls libraries.

Choose correct statements about software frameworks.

  • a. They follow the hollywood principle, otherwise known as β€˜inversion of control’
  • b. They come with full or partial implementation.
  • c. They are more concrete than patterns or principles.
  • d. They are often configurable.
  • e. They are reuse mechanisms.
  • f. They are similar to reusable libraries but bigger.

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

Explanation: While both libraries and frameworks are reuse mechanisms, and both more concrete than principles and patterns, libraries differ from frameworks in some key ways. One of them is the β€˜inversion of control’ used by frameworks but not libraries. Furthermore, frameworks do not have to be bigger than libraries all the time.

Which one of these are frameworks ?

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

Explanation: These are frameworks.

Platforms

Implementation β†’ Reuse β†’ Platforms β†’

What

A platform provides a runtime environment for applications. A platform is often bundled with various libraries, tools, frameworks, and technologies in addition to a runtime environment but the defining characteristic of a software platform is the presence of a runtime environment.

πŸ“¦ Technically, an operating system can be called a platform. For example, Windows PC is a platform for desktop applications while iOS is a platform for mobile apps.

πŸ“¦ Two well-known examples of platforms are JavaEE and .NET, both of which sit above Operating systems layer, and are used to develop enterprise applications. Infrastructure services such as connection pooling, load balancing, remote code execution, transaction management, authentication, security, messaging etc. are done similarly in most enterprise applications. Both JavaEE and .NET provide these services to applications in a customizable way without developers having to implement them from scratch every time.

  • JavaEE (Java Enterprise Edition) is both a framework and a platform for writing enterprise applications. The runtime used by the JavaEE applications is the JVM (Java Virtual Machine) that can run on different Operating Systems.
  • .NET is a similar platform and a framework. Its runtime is called CLR (Common Language Runtime) and usually used on Windows machines.

Enterprise Application: β€˜enterprise applications’ means software applications used at organizations level and therefore has to meet much higher demands (such as in scalability, security, performance, and robustness) than software meant for individual use.

Cloud Computing

Implementation β†’ Reuse β†’ Cloud Computing β†’

What

Cloud computing is the delivery of computing as a service over the network, rather than a product running on a local machine. This means the actual hardware and software is located at a remote location, typically, at a large server farm, while users access them over the network. Maintenance of the hardware and software is managed by the cloud provider while users typically pay for only the amount of services they use. This model is similar to the consumption of electricity; the power company manages the power plant, while the consumers pay them only for the electricity used. The cloud computing model optimizes hardware and software utilization and reduces the cost to consumers. Furthermore, users can scale up/down their utilization at will without having to upgrade their hardware and software. The traditional non-cloud model of computing is similar to everyone buying their own generators to create electricity for their own use.

Implementation β†’ Reuse β†’ Cloud Computing β†’

Iaas, PaaS, and SaaS


source:https://commons.wikimedia.org

Cloud computing can deliver computing services at three levels:

  1. Infrastructure as a service (IaaS) delivers computer infrastructure as a service. For example, a user can deploy virtual servers on the cloud instead of buying physical hardware and installing server software on them. Another example would be a customer using storage space on the cloud for off-site storage of data. Β Rackspace is an example of an IaaS cloud provider. Amazon Elastic Compute Cloud (Amazon EC2) is another one.

  2. Platform as a service (PaaS) provides a platform on which developers can build applications. Developers do not have to worry about infrastructure issues such as deploying servers or load balancing as is required when using IaaS. Those aspects are automatically taken care of by the platform. The price to pay is reduced flexibility; applications written on PaaS are limited to facilities provided by the platform. Β A PaaS example is the Google App Engine where developers can build applications using Java, Python, PHP, or Go whereas Amazon EC2 allows users to deploy application written in any language on their virtual servers.

  3. Software as a service (SaaS) allows applications to be accessed over the network instead of installing them on a local machine. Β For example, Google Docs is an SaaS word processing software, while Microsoft Word is a traditional word processing software.

Google Calendar belongs to which category of cloud computing services?

  • a. IaaS
  • b. PaaS
  • c. SaaS

(c)

Explanation: It is a software as a service. Instead of installing a calendar software on your desktop, we can use the Google Calendar software that lives β€˜on the cloud’.

Documentation

Introduction

Implementation β†’ Documentation β†’ Introduction β†’

What

Developer-to-developer documentation can be in one of two forms:

  1. Documentation for developer-as-user: Software components are written by developers and reused by other developers, which means there is a need to document how such components are to be used. Such documentation can take several forms:
    • API documentation: APIs expose functionality in small-sized, independent and easy-to-use chunks, each of which can be documented systematically.
    • Tutorial-style instructional documentation: In addition to explaining functions/methods independently, some higher-level explanations of how to use an API can be useful.

  1. Documentation for developer-as-maintainer: There is a need to document how a system or a component is designed, implemented and tested so that other developers can maintain and evolve the code. Writing documentation of this type is harder because of the need to explain complex internal details. However, given that readers of this type of documentation usually have access to the source code itself, only some information need to be included in the documentation, as code (and code comments) can also serve as a complementary source of information.

Choose correct statements about API documentation.

  • a. They are useful for both developers who use the API and developers who maintain the API implementation.
  • b. There are tools that can generate API documents from code comments.
  • d. API documentation may contain code examples.

All

Guidelines

Given below are some guidelines to write developer documentation.

Guideline: Aim for Comprehensibility

Implementation β†’ Documentation β†’ Guidelines β†’ Aim for Comprehensibility β†’

What

Technical documents exist to help others understand technical details. Therefore, it is not enough for the documentation to be accurate and comprehensive, it should also be comprehensible too.

Implementation β†’ Documentation β†’ Guidelines β†’ Aim for Comprehensibility β†’

How

Here are some tips on writing effective documentation.

  • Use plenty of diagrams: It is not enough to explain something in words; complement it with visual illustrations (e.g. a UML diagram).
  • Use plenty of examples: When explaining algorithms, show a running example to illustrate each step of the algorithm, in parallel to worded explanations.
  • Use simple and direct explanations: Convoluted explanations and fancy words will annoy readers. Avoid long sentences.
  • Get rid of statements that do not add value: For example, 'We made sure our system works perfectly' (who didn't?), 'Component X has its own responsibilities' (of course it has!).
  • It is not a good idea to have separate sections for each type of artifact, such as 'use cases', 'sequence diagrams', 'activity diagrams', etc. Such a structure, coupled with the indiscriminate inclusion of diagrams without justifying their need, indicates a failure to understand the purpose of documentation. Include diagrams when they are needed to explain something. If you want to provide additional diagrams for completeness' sake, include them in the appendix as a reference.

It is recommended for developer documents,

  • a. to have separate sections for each type of diagrams such as class diagrams, sequence diagrams, use case diagrams etc.
  • b. to give a high priority to comprehension too, not stop at comprehensiveness only.

(a)(b)

Explanation:

(a) Use diagrams when they help to understand the text descriptions. Text and diagrams should be used in tandem. Having separate sections for each diagram type is a sign of generating diagrams for the sake of having them.

(b) Both are important, but lengthy, complete, accurate yet hard to understand documents are not that useful.

Guideline: Document Minimally, but Sufficiently

Implementation β†’ Documentation β†’ Guidelines β†’ Minimal but Sufficient β†’

What

Aim for 'just enough' developer documentation.

  • Writing and maintaining developer documents is an overhead. You should try to minimize that overhead.
  • If the readers are developers who will eventually read the code, the documentation should complement the code and should provide only just enough guidance to get started.

Implementation β†’ Documentation β†’ Guidelines β†’ Minimal but Sufficient β†’

How

Anything that is already clear in the code need not be described in words. Instead, focus on providing higher level information that is not readily visible in the code or comments.

Refrain from duplicating chunks or text. When describing several similar algorithms/designs/APIs, etc., do not simply duplicate large chunks of text. Instead, describe the similarity in one place and emphasize only the differences in other places. It is very annoying to see pages and pages of similar text without any indication as to how they differ from each other.


SECTION: QUALITY ASSURANCE

Testing

Introduction

Quality Assurance β†’ Testing β†’

What

Testing: Testing is operating a system or component under specified conditions, observing or recording the results, and making an evaluation of some aspect of the system or component. –- source: IEEE

When testing, we execute a set of test cases. A test case specifies how to perform a test. At a minimum, it specifies the input to the software under test (SUT) and the expected behavior.

πŸ“¦ Example: A minimal test case for testing a browser:

  • Input – Start the browser using a blank page (vertical scrollbar disabled). Then, load longfile.html located in the test data folder.
  • Expected behavior – The scrollbar should be automatically enabled upon loading longfile.html.

Test cases can be determined based on the specification, reviewing similar existing systems, or comparing to the past behavior of the SUT.

A more elaborate test case can have other details such as those given below.

  • A unique identifier : e.g. TC0034-a
  • A descriptive name: e.g. vertical scrollbar activation for long web pages
  • Objectives: e.g. to check whether the vertical scrollbar is correctly activated when a long web page is loaded to the browser
  • Classification information: e.g. priority - medium, category - UI features
  • Cleanup, if any: e.g. empty the browser cache.

For each test case we do the following:

  1. Feed the input to the SUT
  2. Observe the actual output
  3. Compare actual output with the expected output

A test case failure is a mismatch between the expected behavior and the actual behavior. A failure is caused by a defect (or a bug).

πŸ“¦ Example: In the browser example above, a test case failure is implied if the scrollbar remains disabled after loading longfile.html. The defect/bug causing that failure could be an uninitialized variable.

Here is another definition of testing:

Software testing consists of the dynamic verification that a program provides expected behaviors on a finite set of test cases, suitably selected from the usually infinite execution domain. -– source: Software Engineering Book of Knowledge V3

Some things to note (indicated by keywords in the above definition):

  • Dynamic: Testing involves executing the software. It is not by examining the code statically.
  • Finite: In most non-trivial cases there are potentially infinite test scenarios but resource constraints dictate that we can test only a finite number of scenarios.
  • Selected: In most cases it is not possible to test all scenarios. That means we need to select what scenarios to test.
  • Expected: Testing requires some knowledge of how the software is expected to behave.

Explain how the concepts of testing, test case, test failure, and defect are related to each other.

Test Automation

Quality Assurance β†’ Testing β†’ Test Automation β†’

What

An automated test case can be run programmatically and the result of the test case (pass or fail) is determined programmatically. Compared to manual testing, automated testing reduces the effort required to run tests repeatedly and increases precision of testing (because manual testing is susceptible to human errors).



Quality Assurance β†’ Testing β†’ Test Automation β†’

Automated Testing of CLI Apps

A simple way to semi-automate testing of a CLI(Command Line Interface) app is by using input/output re-direction.

  • First, we feed the app with a sequence of test inputs that is stored in a file while redirecting the output to another file.
  • Next, we compare the actual output file with another file containing the expected output.

Let us assume we are testing a CLI app called AddressBook. Here are the detailed steps:

  1. Store the test input in the text file input.txt.

    add Valid Name p/12345 valid@email.butNoPrefix
    add Valid Name 12345 e/valid@email.butPhonePrefixMissing
    
  2. Store the output we expect from the SUT in another text file expected.txt.

    Command: || [add Valid Name p/12345 valid@email.butNoPrefix]
    Invalid command format: add 
    
    Command: || [add Valid Name 12345 e/valid@email.butPhonePrefixMissing]
    Invalid command format: add 
    
  3. Run the program as given below, which will redirect the text in input.txt as the input to AddressBook and similarly, will redirect the output of AddressBook to a text file output.txt. Note that this does not require any code changes to AddressBook.

    java AddressBook < input.txt > output.txt
    
    • πŸ’‘ The way to run a CLI program differs based on the language.
      e.g., In Python, assuming the code is in AddressBook.py file, use the command
      python AddressBook.py < input.txt > output.txt

    • πŸ’‘ If you are using Windows, use a normal command window to run the app, not a Power Shell window.

    A CLI program takes input from the keyboard and outputs to the console. That is because those two are default input and output streams, respectively. But you can change that behavior using < and > operators. For example, if you run AddressBook in a command window, the output will be shown in the console, but if you run it like this,

    java AddressBook > output.txt 
    

    the Operating System then creates a file output.txt and stores the output in that file instead of displaying it in the console. No file I/O coding is required. Similarly, adding < input.txt (or any other filename) makes the OS redirect the contents of the file as input to the program, as if the user typed the content of the file one line at a time.

    πŸ“Ž Resources:

  4. Next, we compare output.txt with the expected.txt. This can be done using a utility such as Windows FC (i.e. File Compare) command, Unix diff command, or a GUI tool such as WinMerge.

    FC output.txt expected.txt
    

Note that the above technique is only suitable when testing CLI apps, and only if the exact output can be predetermined. If the output varies from one run to the other (e.g. it contains a time stamp), this technique will not work. In those cases we need more sophisticated ways of automating tests.

CLI App: An application that has a Command Line Interface. i.e. user interacts with the app by typing in commands.

Testing Types

Regression Testing

Quality Assurance β†’ Testing β†’ Regression Testing β†’

What

When we modify a system, the modification may result in some unintended and undesirable effects on the system. Such an effect is called a regression.

Regression testing is re-testing the software to detect regressions. Note that to detect regressions, we need to retest all related components, even if they were tested before.

Regression testing is more effective when it is done frequently, after each small change. However, doing so can be prohibitively expensive if testing is done manually. Hence, regression testing is more practical when it is automated.

Regression testing is the automated re-testing of a software after it has been modified.

c.

Explanation: Regression testing need not be automated but automation is highly recommended.

Explain why and when you would do regression testing in a software project.

Unit Testing

Quality Assurance β†’ Testing β†’ Unit Testing β†’

What

Unit testing : testing individual units (methods, classes, subsystems, ...) to ensure each piece works correctly.

In OOP code, it is common to write one or more unit tests for each public method of a class.

πŸ“¦ Here are the code skeletons for a Foo class containing two methods and a FooTest class that contains JUnit tests for those two methods.

class Foo{
    String read(){
        //...
    }
    
    void write(String input){
        //...
    }
    
}

class FooTest{
    
    @Test
    void read(){
        //a unit test for Foo#read() method
    }
    
    @Test
    void write_emptyInput_exceptionThrown(){
        //a unit tests for Foo#write(String) method
    }  
    
    @Test
    void write_normalInput_writtenCorrectly(){
        //another unit tests for Foo#write(String) method
    }
}

Side readings:

Integration Testing

Quality Assurance β†’ Testing β†’ Integration Testing β†’

What

Integration testing : testing whether different parts of the software work together (i.e. integrates) as expected. Integration tests aim to discover bugs in the 'glue code' related to how components interact with each other. These bugs are often the result of misunderstanding of what the parts are supposed to do vs what the parts are actually doing.

πŸ“¦ Suppose a class Car users classes Engine and Wheel. If the Car class assumed a Wheel can support 200 mph speed but the Wheel can only support 150 mph, it is the integration test that is supposed to uncover this discrepancy.

System Testing

Quality Assurance β†’ Testing β†’ System Testing β†’

What

System testing: take the whole system and test it against the system specification.

System testing is typically done by a testing team (also called a QA team).

System test cases are based on the specified external behavior of the system. Sometimes, system tests go beyond the bounds defined in the specification. This is useful when testing that the system fails 'gracefully' having pushed beyond its limits.

πŸ“¦ Suppose the SUT is a browser capable of handling web pages containing up to 5000 characters. Given below is a test case to test if the SUT fails gracefully if pushed beyond its limits.

Test case: load a web page that is too big
* Input: load a web page containing more than 5000 characters. 
* Expected behavior: abort the loading of the page and show a meaningful error message. 

This test case would fail if the browser attempted to load the large file anyway and crashed.

System testing includes testing against non-functional requirements too. Here are some examples.

  • Performance testing – to ensure the system responds quickly.
  • Load testing (also called stress testing or scalability testing) – to ensure the system can work under heavy load.
  • Security testing – to test how secure the system is.
  • Compatibility testing, interoperability testing – to check whether the system can work with other systems.
  • Usability testing – to test how easy it is to use the system.
  • Portability testing – to test whether the system works on different platforms.

Alpha-Beta Testing

Quality Assurance β†’ Testing β†’ Alpha/Beta Testing β†’

What

Alpha testing is performed by the users, under controlled conditions set by the software development team.

Beta testing is performed by a selected subset of target users of the system in their natural work setting.

An open beta release is the release of not-yet-production-quality-but-almost-there software to the general population. For example, Google’s Gmail was in 'beta' for many years before the label was finally removed.

Developer Testing

Quality Assurance β†’ Testing β†’ Developer Testing β†’

What

Developer testing is the testing done by the developers themselves as opposed to professional testers or end-users.

Quality Assurance β†’ Testing β†’ Developer Testing β†’

Why

Delaying testing until the full product is complete has a number of disadvantages:

  • Locating the cause of such a test case failure is difficult due to a large search space; in a large system, the search space could be millions of lines of code, written by hundreds of developers! The failure may also be due to multiple inter-related bugs.
  • Fixing a bug found during such testing could result in major rework, especially if the bug originated during the design or during requirements specification (i.e. a faulty design or faulty requirements).
  • One bug might 'hide' other bugs, which could emerge only after the first bug is fixed.
  • The delivery may have to be delayed if too many bugs were found during testing.

Therefore, it is better to do early testing, as hinted by the popular rule of thumb given below, also illustrated by the graph below it.

The earlier a bug is found, the easier and cheaper to have it fixed.

Such early testing of partially developed software is usually, and by necessity, done by the developers themselves i.e. developer testing.

Discuss pros and cons of developers testing their own code.

Pros:

  • Can be done early (the earlier we find a bug, the cheaper it is to fix).
  • Can be done at lower levels, for examples, at operation and class level (testers usually test the system at UI level).
  • It is possible to do more thorough testing because developers know the expected external behavior as well as the internal structure of the component.
  • It forces developers to take responsibility for their own work (they cannot claim that "testing is the job of the testers").

Cons:

  • A developer may unconsciously test only situations that he knows to work (i.e. test it too 'gently').
  • A developer may be blind to his own mistakes (if he did not consider a certain combination of input while writing code, it is possible for him to miss it again during testing).
  • A developer may have misunderstood what the SUT is supposed to do in the first place.
  • A developer may lack the testing expertise.

The cost of fixing a bug goes down as we reach the product release.

False. The cost goes up over time.

Explain why early testing by developers is important.

Acceptance Testing

Quality Assurance β†’ Testing β†’ Acceptance Testing β†’

What

Acceptance testing (aka User Acceptance Testing (UAT)): test the delivered system to ensure it meets the user requirements.

Acceptance tests give an assurance to the customer that the system does what it is intended to do. Acceptance test cases are often defined at the beginning of the project, usually based on the use case specification. Successful completion of UAT is often a prerequisite to the project sign-off.

Quality Assurance β†’ Testing β†’ Acceptance Testing β†’

Acceptance vs System Testing

Acceptance testing comes after system testing. Similar to system testing, acceptance testing involves testing the whole system.

Some differences between system testing and acceptance testing:

System Testing Acceptance Testing
Done against the system specification Done against the requirements specification
Done by testers of the project team Done by a team that represents the customer
Done on the development environment or a test bed Done on the deployment site or on a close simulation of the deployment site
Both negative and positive test cases More focus on positive test cases

Note: negative test cases: cases where the SUT is not expected to work normally e.g. incorrect inputs; positive test cases: cases where the SUT is expected to work normally

Requirement Specification vs System Specification

The requirement specification need not be the same as the system specification. Some example differences:

Requirements Specification System Specification
limited to how the system behaves in normal working conditions can also include details on how it will fail gracefully when pushed beyond limits, how to recover, etc. specification
written in terms of problems that need to be solved (e.g. provide a method to locate an email quickly) written in terms of how the system solve those problems (e.g. explain the email search feature)
specifies the interface available for intended end-users could contain additional APIs not available for end-users (for the use of developers/testers)

However, in many cases one document serves as both a requirement specification and a system specification.

Passing system tests does not necessarily mean passing acceptance testing. Some examples:

  • The system might work on the testbed environments but might not work the same way in the deployment environment, due to subtle differences between the two environments.
  • The system might conform to the system specification but could fail to solve the problem it was supposed to solve for the user, due to flaws in the system design.

Choose the correct statements about system testing and acceptance testing.

  • a. Both system testing and acceptance testing typically involve the whole system.
  • b. System testing is typically more extensive than acceptance testing.
  • c. System testing can include testing for non-functional qualities.
  • d. Acceptance testing typically has more user involvement than system testing.
  • e. In smaller projects, the developers may do system testing as well, in addition to developer testing.
  • f. If system testing is adequately done, we need not do acceptance testing.

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

Explanation:

(b) is correct because system testing can aim to cover all specified behaviors and can even go beyond the system specification. Therefore, system testing is typically more extensive than acceptance testing.

(f) is incorrect because it is possible for a system to pass system tests but fail acceptance tests.

Test Case Design

Introduction

Quality Assurance β†’ Test Case Design β†’ Introduction β†’

What

Except for trivial SUTs, exhaustive testing is not practical because such testing often requires a massive/infinite number of test cases.

πŸ“¦ Consider the test cases for adding a String object to a Collection object:

  • Add an item to an empty collection.
  • Add an item when there is one item in the collection.
  • Add an item when there are 2, 3, .... n items in the collection.
  • Add an item that has an English, a French, a Spanish, ... word.
  • Add an item that is the same as an existing item.
  • Add an item immediately after adding another item.
  • Add an item immediately after system startup.
  • ...

Exhaustive testing of this operation can take many more test cases.

Program testing can be used to show the presence of bugs, but never to show their absence!
--Edsger Dijkstra

Every test case adds to the cost of testing. In some systems, a single test case can cost thousands of dollars Β e.g. on-field testing of flight-control software. Therefore, test cases need to be designed to make the best use of testing resources. In particular:

  • Testing should be effective i.e., it finds a high % of existing bugs Β e.g., a set of test cases that finds 60 defects is more effective than a set that finds only 30 defects in the same system.

  • Testing should be efficient i.e., it has a high rate of success (bugs found/test cases) Β a set of 20 test cases that finds 8 defects is more efficient than another set of 40 test cases that finds the same 8 defects.

For testing to be E&E, each new test we add should be targeting a potential fault that is not already targeted by existing test cases. There are test case design techniques that can help us improve E&E of testing.

Given below is the sample output from a text-based program TriangleDetector ithat determines whether the three input numbers make up the three sides of a valid triangle. List test cases you would use to test this software. Two sample test cases are given below.

C:\> java TriangleDetector
Enter side 1: 34
Enter side 2: 34
Enter side 3: 32
Can this be a triangle?:  Yes
Enter side 1:

Sample test cases,

34,34,34: Yes
0, any valid, any valid: No

In addition to obvious test cases such as

  • sum of two sides == third,
  • sum of two sides < third ...

We may also devise some interesting test cases such as the ones depicted below.

Note that their applicability depends on the context in which the software is operating.

  • Non-integer number, negative numbers, 0, numbers formatted differently (e.g. 13F), very large numbers (e.g. MAX_INT), numbers with many decimal places, empty string, ...
  • Check many triangles one after the other (will the system run out of memory?)
  • Backspace, tab, CTRL+C , …
  • Introduce a long delay between entering data (will the program be affected by, say the screensaver?), minimize and restore window during the operation, hibernate the system in the middle of a calculation, start with invalid inputs (the system may perform error handling differently for the very first test case), …
  • Test on different locale.

The main point to note is how difficult it is to test exhaustively, even on a trivial system.

Explain the why exhaustive testing is not practical using the example of testing Logic#newGame() operation in the Minesweeper game.

Consider this sequence of test cases:

  • Test case 1. Start Minesweeper. Activate newGame() and see if it works.
  • Test case 2. Start Minesweeper. Activate newGame(). Activate newGame() again and see if it works.
  • Test case 3. Start Minesweeper. Activate newGame() three times consecutively and see if it works.
  • …
  • Test case 267. Start Minesweeper. Activate newGame() 267 times consecutively and see if it works.

Well, you get the idea. Exhaustive testing of newGame() is not practical.

Improving efficiency and effectiveness of test case design can,

  • a. improve the quality of the SUT.
  • b. save money.
  • c. save time spent on test execution.
  • d. save effort on writing and maintaining tests.
  • e. minimize redundant test cases.
  • f. forces us to understand the SUT better.

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

Quality Assurance β†’ Test Case Design β†’ Introduction β†’

Black Box vs Glass Box

Test case design can be of three types, based on how much of SUT internal details are considered when designing test cases:

  • Black-box (aka specification-based or responsibility-based) approach: test cases are designed exclusively based on the SUT’s specified external behavior.

  • White-box (aka glass-box or structured or implementation-based) approach: test cases are designed based on what is known about the SUT’s implementation, i.e. the code.

  • Gray-box approach: test case design uses some important information about the implementation. For example, if the implementation of a sort operation uses different algorithms to sort lists shorter than 1000 items and lists longer than 1000 items, more meaningful test cases can then be added to verify the correctness of both algorithms.

Equivalence Partitions

Quality Assurance β†’ Test Case Design β†’ Equivalence Partitions β†’

What

Consider the testing of the following operation.

isValidMonth (int m): boolean : returns true if m is in the range [1..12]

It is inefficient and impractical to test this method for all integer values [-MIN_INT to MAX_INT]. Fortunately, there is no need to test all possible input values. For example, if the input value 233 failed to produce the correct result, the input 234 is likely to fail too; there is no need to test both.

In general, most SUTs do not treat each input in a unique way. Instead, they process all possible inputs in a small number of distinct ways. That means a range of inputs is treated the same way inside the SUT. Equivalence partitioning (EP) is a test case design technique that uses the above observation to improve the E&E of testing.

Equivalence partition (aka equivalence class): A group of test inputs that are likely to be processed by the SUT in the same way.

By dividing possible inputs into equivalence partitions we can,

  • avoid testing too many inputs from one partition. Testing too many inputs from the same partition is unlikely to find new bugs. This increases the efficiency of testing by reducing redundant test cases.
  • ensure all partitions are tested. Missing partitions can result in bugs going unnoticed. This increases the effectiveness of testing by increasing the chance of finding bugs.

Quality Assurance β†’ Test Case Design β†’ Equivalence Partitions β†’

Basic

Equivalence partitions (EPs) are usually derived from the specifications of the SUT.

πŸ“¦ These could be EPs for the isValidMonth example:

  • [MIN_INT ... 0] : below the range that produces true
  • [1 … 12] : the range that produces true
  • [13 … MAX_INT] : above the range that produces true

isValidMonth (int m): boolean : returns true if m is in the range [1..12]

When the SUT has multiple inputs, you should identify EPs for each input.

πŸ“¦ Consider the method duplicate(String s, int n): String which returns a String that contains s repeated n times.

Example EPs for s:

  • zero-length strings
  • string containing whitespaces
  • ...

Example EPs for n:

  • 0
  • negative values
  • ...

An EP may not have adjacent values.

πŸ“¦ Consider the method isPrime(int i):boolean that returns true if i is a prime number.

EPs for i:

  • prime numbers
  • non-prime numbers

Some inputs have only a small number of possible values and a potentially unique behavior for each value. In those cases we have to consider each value as a partition by itself.

πŸ“¦ Consider the method showStatusMessage(GameStatus s):String that returns a unique String for each of the possible value of s (GameStatus is an enum). In this case, each possible value for s will have to be considered as a partition.

Note that the EP technique is merely a heuristic and not an exact science, especially when applied manually (as opposed to using an automated program analysis tool to derive EPs). The partitions derived depend on how one β€˜speculates’ the SUT to behave internally. Applying EP under a glass-box or gray-box approach can yield more precise partitions.

πŸ“¦ Consider the method EPs given above for the isValidMonth. A different tester might use these EPs instead:

  • [1 … 12] : the range that produces true
  • [all other integers] : the range that produces false

πŸ“¦ Some more examples:

Specification Equivalence partitions

isValidFlag(String s): boolean
Returns true if s is one of [β€œF”, β€œT”, β€œD”]. The comparison is case-sensitive.

[β€œF”] [β€œT”] [β€œD”] [β€œf”, β€œt”, β€œd”] [any other string][null]

squareRoot(String s): int
Pre-conditions: s represents a positive integer
Returns the square root of s if the square root is an integer; returns 0 otherwise.

[s is not a valid number] [s is a negative integer] [s has an integer square root] [s does not have an integer square root]

Consider this SUT:

isValidName (String s): boolean

Description: returns true if s is not null and not longer than 50 characters.

A. Which one of these is least likely to be an equivalence partition for the parameter s of the isValidName method given below?

B. If you had to choose 3 test cases from the 4 given below, which one will you leave out based on the EP technique?

A. (d)

Explanation: The description does not mention anything about the content of the string. Therefore, the method is unlikely to behave differently for strings consisting of numbers.

B. (a) or (c)

Explanation: both belong to the same EP

Quality Assurance β†’ Test Case Design β†’ Equivalence Partitions β†’

Intermediate

When deciding EPs of OOP methods, we need to identify EPs of all data participants that can potentially influence the behaviour of the method, such as,

  • the target object of the method call
  • input parameters of the method call
  • other data/objects accessed by the method such as global variables. This category may not be applicable if using the black box approach (because the test case designer using the black box approach will not know how the method is implemented)

πŸ“¦ Consider this method in the DataStack class:

/**
 * Adds o to the top of the stack if the stack is not full.
 * @throws MutabilityException if the global flag FREEZE==true.
 * @throws InvalidValueException if  o is null.
 * @return true if the push operation was a success.
 */
boolean push(Object o) {
    ...
}

EPs:

  • DataStack object: [full] [not full]
  • o: [null] [not null]
  • FREEZE: [true][false]

πŸ“¦ Consider a simple Minesweeper app. What are the EPs for the newGame() method of the Logic component?

As newGame() does not have any parameters, the only obvious participant is the Logic object itself.

Note that if the glass-box or the grey-box approach is used, other associated objects that are involved in the method might also be included as participants. For example, Minefield object can be considered as another participant of the newGame() method. Here, the black-box approach is assumed.

Next, let us identify equivalence partitions for each participant. Will the newGame() method behave differently for different Logic objects? If yes, how will it differ? In this case, yes, it might behave differently based on the game state. Therefore, the equivalence partitions are:

  • PRE_GAME : before the game starts, minefield does not exist yet
  • READY : a new minefield has been created and waiting for player’s first move
  • IN_PLAY : the current minefield is already in use
  • WON, LOST : let us assume the newGame behaves the same way for these two values

πŸ“¦ Consider the Logic component of the Minesweeper application. What are the EPs for the markCellAt(int x, int y) method?. The partitions in bold represent valid inputs.

  • Logic: PRE_GAME, READY, IN_PLAY, WON, LOST
  • x: [MIN_INT..-1] [0..(W-1)] [W..MAX_INT] (we assume a minefield size of WxH)
  • y: [MIN_INT..-1] [0..(H-1)] [H..MAX_INT]
  • Cell at (x,y): HIDDEN, MARKED, CLEARED

A test case for the push method can be a combination of the equivalence partitions. Given below is such a test case.

  • id: DataStack_Push_001
  • description: checks whether pushing onto a full stack works correctly
  • input: stack is full, o != null, FREEZE == false
  • expected output: returns false, stack remains unchanged

Boundary Value Analysis

Quality Assurance β†’ Test Case Design β†’ Boundary Value Analysis β†’

What

Boundary Value Analysis (BVA) is test case design heuristic that is based on the observation that bugs often result from incorrect handling of boundaries of equivalence partitions. This is not surprising, as the end points of the boundary are often used in branching instructions etc. where the programmer can make mistakes.

πŸ“¦ markCellAt(int x, int y) operation could contain code such as if (x > 0 && x < = (W-1)) which involves boundaries of x’s equivalence partitions.

BVA suggests that when picking test inputs from an equivalence partition, values near boundaries (i.e. boundary values) are more likely to find bugs.

Boundary values are sometimes called corner cases.

Boundary value analysis recommends testing only values that reside on the equivalence class boundary.

False

Explanation: It does not recommend testing only those values on the boundary. It merely suggests that values on and around a boundary are more likely to cause errors.

Quality Assurance β†’ Test Case Design β†’ Boundary Value Analysis β†’

How

Typically, we choose three values around the boundary to test: one value from the boundary, one value just below the boundary, and one value just above the boundary. The number of values to pick depends on other factors, such as the cost of each test case.

πŸ“¦ Some examples:

Equivalence partition Some possible boundary values

[1-12]

0,1,2, 11,12,13

[MIN_INT, 0]
(MIN_INT is the minimum possible integer value allowed by the environment)

MIN_INT, MIN_INT+1, -1, 0 , 1

[any non-null String]

Empty String, a String of maximum possible length

[prime numbers]
[β€œF”]
[β€œA”, β€œD”, β€œX”]

No specific boundary
No specific boundary
No specific boundary

[non-empty Stack]
(we assume a fixed size stack)

Stack with: one element, two elements, no empty spaces, only one empty space

Quality Assurance

Introduction

Quality Assurance β†’ Quality Assurance β†’ Introduction β†’

What

Software Quality Assurance (QA) is the process of ensuring that the software being built has the required levels of quality.

While testing is the most common activity used in QA, there are other complementary techniques such as static analysis, code reviews, and formal verification.

Quality Assurance β†’ Quality Assurance β†’ Introduction β†’

Validation vs Verification

Quality Assurance = Validation + Verification

QA involves checking two aspects:

  1. Validation: are we building the right system i.e., are the requirements correct?
  2. Verification: are we building the system right i.e., are the requirements implemented correctly?

Whether something belongs under validation or verification is not that important. What is more important is both are done, instead of limiting to verification (i.e., remember that the requirements can be wrong too).

Choose the correct statements about validation and verification.

  • a. Validation: Are we building the right product?, Verification: Are we building the product right?
  • b. It is very important to clearly distinguish between validation and verification.
  • c. The important thing about validation and verification is to remember to pay adequate attention to both.
  • d. Developer-testing is more about verification than validation.
  • e. QA covers both validation and verification.
  • f. A system crash is more likely to be a verification failure than a validation failure.

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

Explanation:

Whether something belongs under validation or verification is not that important. What is more important is that we do both.

Developer testing is more about bugs in code, rather than bugs in the requirements.

In QA, system testing is more about verification (does the system follow the specification?) and acceptance testings is more about validation (does the system solve the user’s problem?).

A system crash is more likely to be a bug in the code, not in the requirements.

Code Reviews

Quality Assurance β†’ Quality Assurance β†’ Code Reviews β†’

What

Code review is the systematic examination code with the intention of finding where the code can be improved.

Reviews can be done in various forms. Some examples below:

  • In pair programming

    • As pair programming involves two programmers working on the same code at the same time, there is an implicit review of the code by the other member of the pair.

Pair Programming:

Pair programming is an agile software development technique in which two programmers work together at one workstation. One, the driver, writes code while the other, the observer or navigator, reviews each line of code as it is typed in. The two programmers switch roles frequently. [source: Wikipedia]


[image credit: Wikipedia]

πŸ“Ί A good introduction to pair programming:

  • Pull Request reviews

    • Project Management Platforms such as GitHub and BitBucket allows the new code to be proposed as Pull Requests and provides the ability for others to review the code in the PR.
  • Formal inspections

    • Inspections involve a group of people systematically examining a project artifacts to discover defects. Members of the inspection team play various roles during the process, such as:

      • the author - the creator of the artifact
      • the moderator - the planner and executor of the inspection meeting
      • the secretary - the recorder of the findings of the inspection
      • the inspector/reviewer - the one who inspects/reviews the artifact.

Advantages of code reviews over testing:

  • It can detect functionality defects as well as other problems such as coding standard violations.
  • Can verify non-code artifacts and incomplete code
  • Do not require test drivers or stubs.

Disadvantages:

  • It is a manual process and therefore, error prone.

Static Analysis

Quality Assurance β†’ Quality Assurance β†’ Static Analysis β†’

What

Static analysis: Static analysis is the analysis of code without actually executing the code.

Static analysis of code can find useful information such unused variables, unhandled exceptions, style errors, and statistics. Most modern IDEs come with some inbuilt static analysis capabilities. For example, an IDE can highlight unused variables as you type the code into the editor.

Higher-end static analyzer tools can perform for more complex analysis such as locating potential bugs, memory leaks, inefficient code structures etc.

πŸ“¦ Some example static analyzer for Java:

Linters are a subset of static analyzers that specifically aim to locate areas where the code can be made 'cleaner'.

Formal Verification

Quality Assurance β†’ Quality Assurance β†’ Formal Verification β†’

What

Formal verification uses mathematical techniques to prove the correctness of a program.

πŸ“Ί An introduction to Formal Methods by Eric Hehner

Advantages:

  • Formal verification can be used to prove the absence of errors. In contrast, testing can only prove the presence of error, not their absence.

Disadvantages:

  • It only proves the compliance with the specification, but not the actual utility of the software.
  • It requires highly specialized notations and knowledge which makes it an expensive technique to administer. Therefore, formal verifications are more commonly used in safety-critical software such as flight control systems.

Testing cannot prove the absence of errors. It can only prove the presence of errors. However, formal methods can prove the absence of errors.

True

Explanation: While using formal methods is more expensive than testing, it indeed can prove the correctness of a piece of software conclusively, in certain contexts. Getting such proof via testing requires exhaustive testing, which is not practical to do in most cases.


SECTION: PROJECT MANAGEMENT

Project Planning

Project Management β†’ Project Planning β†’

Work Breakdown Structure

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 project for developing a game.

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:

πŸ‘Ž Not good πŸ‘ 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.

Project Management β†’ Project Planning β†’

Milestones

A milestone is the end of a stage which indicates a significant progress. We 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, we 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

Project Management β†’ Project Planning β†’

Buffers

A buffer is a 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 is 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 a feedback to improve future effort estimates.

Project Management β†’ Project Planning β†’

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 track tasks using simple tools as online spreadsheets or general-purpose/light-weight tasks 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):

Project Management β†’ Project Planning β†’

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.

Project Management β†’ Project Planning β†’

PERT Charts

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

  • Node or vertex captures the effort estimation of a task, and
  • Arrow depicts 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.

Teamwork

Project Management β†’ Teamwork β†’

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 expert, network technology expert, etc. This allows individual group members to concentrate solely on the areas where they have sound knowledge and expertise.

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

Strict hierarchy team

In 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 bureaucratic government. Each team member only works on his 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, Egoless team structure seems most suitable for a school project. However, given school projects are low-stakes, short-lived, and small, even the other two team structures can be used for them.

SDLC Process Models

Introduction

Project Management β†’ SDLC Process Models β†’ Introduction β†’

What

Software development goes through different stages such as requirements, analysis, design, implementation and testing. These stages are collectively known as the software development life cycle (SDLC). There are several approaches, known as software development life cycle models (also called software process models) that describe different ways to go through the SDLC. Each process model prescribes a "roadmap" for the software developers to manage the development effort. The roadmap describes the aims of the development stage(s), the artifacts or outcome of each stage as well as the workflow i.e. the relationship between stages.

Project Management β†’ SDLC Process Models β†’ Introduction β†’

Sequential Models

The sequential model, also called the waterfall model, models software development as a linear process, in which the project is seen as progressing steadily in one direction through the development stages. The name waterfall stems from how the model is drawn to look like a waterfall (see below).

When one stage of the process is completed, it should produce some artifacts to be used in the next stage. For example, upon completion of the requirement stage a comprehensive list of requirements is produced that will see no further modifications. A strict application of the sequential model would require each stage to be completed before starting the next.

This could be a useful model when the problem statement that is well-understood and stable. In such cases, using the sequential model should result in a timely and systematic development effort, provided that all goes well. As each stage has a well-defined outcome, the progress of the project can be tracked with a relative ease.

The major problem with this model is that requirements of a real-world project are rarely well-understood at the beginning and keep changing over time. One reason for this is that users are generally not aware of how a software application can be used without prior experience in using a similar application.

Project Management β†’ SDLC Process Models β†’ Introduction β†’

Iterative Models

The iterative model (sometimes called iterative and incremental) advocates having several iterations of SDLC. Each of the iterations could potentially go through all the development stages, from requirement gathering to testing & deployment. Roughly, it appears to be similar to several cycles of the sequential model.

In this model, each of the iterations produces a new version of the product. Feedback on the version can then be fed to the next iteration. Taking the Minesweeper game as an example, the iterative model will deliver a fully playable version from the early iterations. However, the first iteration will have primitive functionality, for example, a clumsy text based UI, fixed board size, limited randomization etc. These functionalities will then be improved in later releases.

The iterative model can take a breadth-first or a depth-first approach to iteration planning.

  • breadth-first: an iteration evolves all major components in parallel.
  • depth-first: an iteration focuses on fleshing out only some components.

Most project use a mixture of breadth-first and depth-first iterations. Hence, the common phrase β€˜an iterative and incremental process’.

Project Management β†’ SDLC Process Models β†’ Introduction β†’

Agile Models

In 2001, a group of prominent software engineering practitioners met and brainstormed for an alternative to documentation-driven, heavyweight software development processes that were used in most large projects at the time. This resulted in something called the agile manifesto (a vision statement of what they were looking to do).

We are uncovering better ways of developing software by doing it and helping others do it.

Through this work we have come to value:

  • Individuals and interactions over processes and tools
  • Working software over comprehensive documentation
  • Customer collaboration over contract negotiation
  • Responding to change over following a plan

That is, while there is value in the items on the right, we value the items on the left more.
Extract from the Agile Manifesto

Subsequently, some of the signatories of the manifesto went on to create process models that try to follow it. These processes are collectively called agile processes. Some of the key features of agile approaches are:

  • Requirements are prioritized based on the needs of the user, are clarified regularly (at times almost on a daily basis) with the entire project team, and are factored into the development schedule as appropriate.
  • Instead of doing a very elaborate and detailed design and a project plan for the whole project, the team works based on a rough project plan and a high level design that evolves as the project goes on.
  • Strong emphasis on complete transparency and responsibility sharing among the team members. The team is responsible together for the delivery of the product. Team members are accountable, and regularly and openly share progress with each other and with the user.

There are a number of agile processes in the development world today. eXtreme Programming (XP) and Scrum are two of the well-known ones.

Choose the correct statements about agile processes.

  • a. They value working software over comprehensive documentation.
  • b. They value responding to change over following a plan.
  • c. They may not be suitable for some type of projects.
  • d. XP and Scrum are agile processes.

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

Example Process Models

Project Management β†’ SDLC Process Models β†’

XP

The following description was adapted from the XP home page, emphasis added:

Extreme Programming (XP) stresses customer satisfaction. Instead of delivering everything you could possibly want on some date far in the future, this process delivers the software you need as you need it.

XP aims to empower developers to confidently respond to changing customer requirements, even late in the life cycle.

XP emphasizes teamwork. Managers, customers, and developers are all equal partners in a collaborative team. XP implements a simple, yet effective environment enabling teams to become highly productive. The team self-organizes around the problem to solve it as efficiently as possible.

XP aims to improve a software project in five essential ways: communication, simplicity, feedback, respect, and courage. Extreme Programmers constantly communicate with their customers and fellow programmers. They keep their design simple and clean. They get feedback by testing their software starting on day one. Every small success deepens their respect for the unique contributions of each and every team member. With this foundation, Extreme Programmers are able to courageously respond to changing requirements and technology.

XP has a set of simple rules. XP is a lot like a jig saw puzzle with many small pieces. Individually the pieces make no sense, but when combined together a complete picture can be seen. This flow chart shows how Extreme Programming's rules work together.

Pair programming, CRC cards, project velocity, and standup meetings are some interesting topics related to XP. Refer to extremeprogramming.org to find out more about XP.

Project Management β†’ SDLC Process Models β†’

Scrum

This description of Scrum was adapted from Wikipedia [retrieved on 18/10/2011], emphasis added:

Scrum is a process skeleton that contains sets of practices and predefined roles. The main roles in Scrum are:

  • The Scrum Master, who maintains the processes (typically in lieu of a project manager)
  • The Product Owner, who represents the stakeholders and the business
  • The Team, a cross-functional group who do the actual analysis, design, implementation, testing, etc.

A Scrum project is divided into iterations called Sprints. A sprint is the basic unit of development in Scrum. Sprints tend to last between one week and one month, and are a timeboxed (i.e. restricted to a specific duration) effort of a constant length.

Each sprint is preceded by a planning meeting, where the tasks for the sprint are identified and an estimated commitment for the sprint goal is made, and followed by a review or retrospective meeting, where the progress is reviewed and lessons for the next sprint are identified.

During each sprint, the team creates a potentially deliverable product increment (for example, working and tested software). The set of features that go into a sprint come from the product backlog, which is a prioritized set of high level requirements of work to be done. Which backlog items go into the sprint is determined during the sprint planning meeting. During this meeting, the Product Owner informs the team of the items in the product backlog that he or she wants completed. The team then determines how much of this they can commit to complete during the next sprint, and records this in the sprint backlog. During a sprint, no one is allowed to change the sprint backlog, which means that the requirements are frozen for that sprint. Development is timeboxed such that the sprint must end on time; if requirements are not completed for any reason they are left out and returned to the product backlog. After a sprint is completed, the team demonstrates the use of the software.

Scrum enables the creation of self-organizing teams by encouraging co-location of all team members, and verbal communication between all team members and disciplines in the project.

A key principle of Scrum is its recognition that during a project the customers can change their minds about what they want and need (often called requirements churn), and that unpredicted challenges cannot be easily addressed in a traditional predictive or planned manner. As such, Scrum adopts an empirical approachβ€”accepting that the problem cannot be fully understood or defined, focusing instead on maximizing the team’s ability to deliver quickly and respond to emerging requirements.

Daily Scrum is another key scrum practice. The description below was adapted from https://www.mountaingoatsoftware.com (emphasis added):

In Scrum, on each day of a sprint, the team holds a daily scrum meeting called the "daily scrum.” Meetings are typically held in the same location and at the same time each day. Ideally, a daily scrum meeting is held in the morning, as it helps set the context for the coming day's work. These scrum meetings are strictly time-boxed to 15 minutes. This keeps the discussion brisk but relevant.

...

During the daily scrum, each team member answers the following three questions:

  • What did you do yesterday?
  • What will you do today?
  • Are there any impediments in your way?

...

The daily scrum meeting is not used as a problem-solving or issue resolution meeting. Issues that are raised are taken offline and usually dealt with by the relevant subgroup immediately after the meeting.

(This is not an endorsement of the product mentioned in the video)

Project Management β†’ SDLC Process Models β†’

Unified Process

The unified process is developed by the Three Amigos - Ivar Jacobson, Grady Booch and James Rumbaugh (the creators of UML).

The unified process consists of four phases: inception, elaboration, construction and transition. The main purpose of each phase can be summarized as follows:

Phase Activities Typical Artifacts
Inception
  • Understand the problem and requirements
  • Communicate with customer
  • Plan the development effort
  • Basic use case model
  • Rough project plan
  • Project vision and scope
Elaboration
  • Refines and expands requirements
  • Determine a high-level design e.g. system architecture
  • System architecture
  • Various design models
  • Prototype
Construction
  • Major implementation effort to support the use cases identified
  • Design models are refined and fleshed out
  • Testing of all levels are carried out
  • Multiple releases of the system
  • Test cases of all levels
  • System release
Transition
  • Ready the system for actual production use
  • Familiarize end users with the system
  • Final system release
  • Instruction manual

Given above is a visualization of a project done using the Unified process (source: Wikipedia). As the diagram shows, a phase can consist of several iterations. Each vertical column (labeled β€œI1” β€œE1”, β€œE2”, β€œC1”, etc.) represents a single iteration. Each of the iterations consists of a set of β€˜workflows’ such as β€˜Business modeling’, β€˜Requirements’, β€˜Analysis & Design’ etc. The shaded region indicates the amount of resource and effort spent on a particular workflow in a particular iteration.

Unified process is a flexible and customizable process model framework rather than a single fixed process. For example, the number of iterations in each phase, definition of workflows, and the intensity of a given workflow in a given iteration can be adjusted according to the nature of the project. Take the Construction Phase, to develop a simple system, one or two iterations would be sufficient. For a more complicated system, multiple iterations will be more helpful. Therefore, the diagram above simply records a particular application of the UP rather than prescribe how the UP is to be applied. However, this record can be refined and reused for similar future projects.

Choose the correct statements about the unified process.

  • a. It was conceived by the three amigos who also created UML.
  • b. The Unified process requires the use of UML.
  • c. The Unified process is actually a process framework rather than a fixed process.
  • d. The Unified process can be iterative and incremental

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

Explanation: Although UP was created by the same three amigos who created UML, the UP does not require UML.

More

Project Management β†’ SDLC Process Models β†’

CMMI

CMMI (Capability Maturity Model Integration) is a process improvement approach defined by Software Engineering Institute at Carnegie Melon University. CMMI provides organizations with the essential elements of effective processes, which will improve their performance. -- adapted from http://www.sei.cmu.edu/cmmi/

CMMI defines five maturity levels for a process and provides criteria to determine if the process of an organization is at a certain maturity level. The diagram below [taken from Wikipedia] gives an overview of the five levels.

Revision Control

Project Management β†’ Revision Control β†’

What

Revision Control Software (RCS) are the software tools that automate the process of Revision Control i.e. managing revisions of software artifacts.

Revision control is also known as Version Control Software (VCS), and a few other names. Here, we use the terms revision and version interchangeably.

Revision control is the process of managing multiple versions of a piece of information. In its simplest form, this is something that many people do by hand: every time you modify a file, save it under a new name that contains a number, each one higher than the number of the preceding version.

Manually managing multiple versions of even a single file is an error-prone task, though, so software tools to help automate this process have long been available. The earliest automated revision control tools were intended to help a single user to manage revisions of a single file. Over the past few decades, the scope of revision control tools has expanded greatly; they now manage multiple files, and help multiple people to work together. The best modern revision control tools have no problem coping with thousands of people working together on projects that consist of hundreds of thousands of files.

There are a number of reasons why you or your team might want to use an automated revision control tool for a project. It will track the history and evolution of your project, so you don't have to. For every change, you'll have a log of who made it; why they made it; when they made it; and what the change was.

When you're working with other people, revision control software makes it easier for you to collaborate. For example, when people more or less simultaneously make potentially incompatible changes, the software will help you to identify and resolve those conflicts.

It can help you to recover from mistakes. If you make a change that later turns out to be an error, you can revert to an earlier version of one or more files. In fact, a really good revision control tool will even help you to efficiently figure out exactly when a problem was introduced.

It will help you to work simultaneously on, and manage the drift between, multiple versions of your project. Most of these reasons are equally valid, at least in theory, whether you're working on a project by yourself, or with a hundred other people.

-- [adapted from bryan-mercurial-guide]



Mercurial: The Definitive Guide by Bryan O'Sullivan retrieved on 2012/07/11

Revision Control Software

In the context of RCS, what is a Revision? Give an example.

Versions of a piece of information. For example, take a file containing program code. If you modify the code and save the file, you have a new version of that file.

  • a. Help a single user manage revisions of a single file
  • b. Help a developer recover from a incorrect modification to a code file
  • c. Makes it easier for a group of developers to collaborate on a project
  • d. Manage the drift between multiple versions of your project
  • e. Detect when multiple developers make incompatible changes to the same file
  • f. All of them are benefits of RCS

f

Suppose You are doing a team project with Tom, Dick, and Harry but those three have not even heard the term RCS. How do you explain RCS to them as briefly as possible, using the project as an example?


SECTION: TOOLS

UML

Class Diagrams

Introduction

Tools β†’ UML β†’ Class Diagrams β†’ Introduction β†’

What

UML class diagrams describe the structure (but not the behavior) of an OOP solution. These are possibly the most often used diagrams in the industry and an indispensable tool for an OO programmer.

πŸ“¦ An example class diagram:

Classes

Tools β†’ UML β†’ Class Diagrams β†’ Classes β†’

What

The basic UML notations used to represent a class:

πŸ“¦ A Table class shown in UML notation:


class Table{
    
    Integer number;
    Chair[] chairs = null;
    
    Integer getNumber(){
        ...
    }
    
    void setNumber(Integer n){
        ...
    }
}

The 'Operations' compartment and/or the 'Attributes' compartment may be omitted if such details are not important for the task at hand. 'Attributes' always appear above the 'Operations' compartment. All operations should be in one compartment rather than each operation in a separate compartment. Same goes for attributes.

The visibility of attributes and operations is used to indicate the level of access allowed for each attribute or operation. The types of visibility and their exact meanings depend on the programming language used. Here are some common visibilities and how they are indicated in a class diagram:

  • + : public
  • - : private
  • # : protected
  • ~ : package private

πŸ“¦ Table class with visibilities shown:

Which of these follow the correct UML notation?

  • 1
  • 2
  • 3
  • 4
  • 5
  1. Incorrect : Attributes compartment should be above the Methods compartment.
  2. Incorrect : All attributes should be inside the same compartment.
  3. Correct
  4. Correct : Both Attributes and Methods compartments can be omitted.
  5. Correct : The Attributes and Methods compartments can be empty.

Draw a UML diagram to represent the Car class as given below. Include visibilities.


class Car{
    
    Engine engine;
    private List<Wheel>[] wheels = null;
    public String model;
    
    public void drive(int speed){
        move(speed);
    }
    
    private move(int speed){
        ...
    }
}

Associations

Tools β†’ UML β†’ Class Diagrams β†’ Associations β†’

Basic

We use a solid line to show an association between two classes.

πŸ“¦ This example shows an association between the Admin class and the Student class:

Tools β†’ UML β†’ Class Diagrams β†’ Associations β†’

We use arrow heads to indication the navigability of an association.

πŸ“¦ Logic is aware of Minefield, but Minefield is not aware of Logic

class Logic{
    Minefield minefield;
}

class Minefield{
    ...
}

Navigability can be shown in class diagrams as well as object diagrams.

Tools β†’ UML β†’ Class Diagrams β†’ Associations β†’

Roles

Association Role labels are used to indicate the role played by the classes in the association.

πŸ“¦ This association represents a marriage between a Man object and a Woman object. The respective roles played by objects of these two classes are husband and wife.

Note how the variable names match closely with the association roles.

class Man{
    Woman wife;
}

class Woman{
    Man husband;
}

πŸ“¦ The role of Student objects in this association is charges (i.e. Admin is in charge of students)

class Admin{
    List<Student> charges;
}

Tools β†’ UML β†’ Class Diagrams β†’ Associations β†’

Labels

Association labels describe the meaning of the association. The arrow head indicates the direction in which the label is to be read.

πŸ“¦ In this example, the same association is described using two different labels.

  • Diagram on the left: Admin class is associated with Student class because an Admin object uses a Student object.
  • Diagram on the right: Admin class is associated with Student class because a Student object is used by an Admin object.

Tools β†’ UML β†’ Class Diagrams β†’ Associations β†’

Multiplicity

Commonly used multiplicities:

  • 0..1 : optional, can be linked to 0 or 1 objects
  • 1 : compulsory, must be linked to one object at all times.
  • * : can be linked to 0 or more objects.
  • n..m : the number of linked objects must be n to m inclusive

πŸ“¦ In the diagram below, an Admin object administers (in charge of) any number of students but a Student object must always be under the charge of exactly one Admin object

πŸ“¦ In the diagram below,

  • Each student must be supervised by exactly one professor. i.e. There cannot be a student who doesn't have a supervisor or has multiple supervisors.
  • A professor cannot supervise more than 5 students but can have no students to supervise.
  • An admin can handle any number of professors and any number of students, including none.
  • A professor/student can be handled by any number of admins, including none.

Associations as Attributes

Tools β†’ UML β†’ Class Diagrams β†’

Associations as Attributes

An association can be shown as an attribute instead of a line.

Association multiplicities and the default value too can be shown as part of the attribute using the following notation. Both are optional.

name: type [multiplicity] = default value

πŸ“¦ The diagram below depicts a multi-player Square Game being played on a board comprising of 100 squares. Each of the squares may be occupied with any number of pieces, each belonging to a certain player.

A Piece may or may not be on a Square. Note how that association can be replaced by an isOn attribute of the Piece class. The isOn attribute can either be null or hold a reference to a Square object, matching the 0..1 multiplicity of the association it replaces. The default value is null.

The association that a Board has 100 Sqaures can be shown in either of these two ways:

Class Level Members

Tools β†’ UML β†’ Class Diagrams β†’

Class-Level Members

In UML class diagrams, underlines denote class-level attributes and variables.

πŸ“¦ In the class below, totalStudents attribute and the getTotalStudents method are class-level.

Composition

Tools β†’ UML β†’ Class Diagrams β†’

Composition

UML uses a solid diamond symbol to denote composition.

Notation:

πŸ“¦ A Book consists of Chapter objects. When the Book object is destroyed, its Chapter objects are destroyed too.

Aggregation

Tools β†’ UML β†’ Class Diagrams β†’

Aggregation

UML uses a hollow diamond is used to indicate an aggregation.

πŸ“¦ Example:

Class Inheritance

Tools β†’ UML β†’ Class Diagrams β†’

Inheritance

You can use a triangle and a solid line (not to be confused with an arrow) to indicate class inheritance.

Notation:

πŸ“¦ Examples: The Car class inherits from the Vehicle class. The Cat and Dog classes inherit from the Pet class.

Object Diagrams

Tools β†’ UML β†’ Object Diagrams β†’

Introduction

An object diagram shows an object structure at a given point of time.

Tools β†’ UML β†’ Object Diagrams β†’

Objects

Notation:

Notes:

  • The class name and object name e.g. car1:Car are underlined.
  • objectName:ClassName is meant to say 'an instance of ClassName identified as objectName'.
  • Unlike classes, there is no compartment for methods.
  • Attributes compartment can be omitted if it is not relevant to the task at hand.
  • Object name can be omitted too e.g. :Car which is meant to say 'an unnamed instance of a Car object'.

πŸ“¦ Some example objects:

Draw a UML diagram to represent the Car object created by the following code.


class Car{
    
    private double price;
    private int speed;
    
    Car(double price, int speed){
        ...
    }
}

// somewhere else in the code base

Car myCar = new Car(13.5, 200);

Tools β†’ UML β†’ Object Diagrams β†’ Associations β†’

What

A solid line indicates an association between two objects.

πŸ“¦ An example object diagram showing two associations:

Activity Diagrams

Introduction

Tools β†’ UML β†’ Activity Diagrams β†’

Introduction

A UML Activity diagram (AD) can model workflows.

An example activity diagram:

[source:wikipeida]

Basic Notations

Tools β†’ UML β†’ Activity Diagrams β†’

Linear Paths

An activity diagram (AD) captures an activity of actions and control flows that makes up the activity.

  • An action is a single step in an activity. It is shown as a rectangle with rounded corners.
  • A control flow shows the flow of control from one action to the next. It is shown by drawing a line with an arrow-head to show the direction of the flow.

Note the slight difference between the start node and the end node which represent the start and the end of the activity, respectively.

πŸ“¦ This activity diagram shows the action sequence of the activity a passenger rides the bus:

Which of these activity diagrams use the correct UML notation?

  • i
  • ii
  • iii
  • iv
  • v

  • i : πŸ‘ Correct. The arrow-head type does not matter.
  • ii : Incorrect. The start and end node notation is swapped.
  • iii : Incorrect. Action boxes should have rounded corners.
  • iv : πŸ‘ Correct. An activity can have only one action.
  • v : Incorrect. There cannot be any double-headed arrows.

Tools β†’ UML β†’ Activity Diagrams β†’

Alternate Paths

A branch node shows the start of alternate paths. Each control flow exiting a branch node has a guard condition : a boolean condition that should be true for execution to take that path. Only one of the guard condition can be true at any time.

A merge node shows the end of alternate paths.

Both branch nodes and merge nodes are diamond shapes. Guard conditions must be in square brackets.

πŸ“¦ The AD below shows alternate paths involved in the workflow of the activity shop for product:

Which of these activity diagrams use the correct UML notation?

  • i
  • ii
  • iii
  • iv
  • v
  • vi

  • i : πŸ‘ Correct. There can be more than two alternate paths.
  • ii : πŸ‘ Correct. An alternate path can divide into more branches.
  • iii : πŸ‘ Correct. A branch can join other branches.
  • iv : Incorrect. At x=5 both guard conditions become true.
  • v : πŸ‘ Correct. It is fine for a branch to form a loop by going back to the original branch node.
  • iv : Incorrect. Guard conditions should be given in square brackets.

Tools β†’ UML β†’ Activity Diagrams β†’

Parallel Paths

Fork nodes indicate the start of concurrent flows of control.

Join nodes indicate the end of parallel paths.

Both have the same notation: a bar.

In a set of parallel paths, execution along all parallel paths should be complete before the execution can start on the outgoing control flow of the join.

πŸ“¦ In this activity diagram (from an online shop website) the actions User browsers products and System records browsing data happen in parallel. Both of them need to finish before the log out action can take place.

Which of these activity diagrams use the correct UML notation?

  • i
  • ii
  • iii
  • iv

  • i : πŸ‘ Correct. There can be more than two parallel paths.
  • ii : Incorrect. All parallel paths that started from a fork should end in the same join node.
  • iii : Incorrect. Parallel paths must end with a join node.
  • iv : πŸ‘ Correct. A parallel path can have multiple actions.

Notes

Tools β†’ UML β†’

Notes

UML notes can augment UML diagrams with additional information. These notes can be shown connected to a particular element in the diagram or can be shown without a connection. The diagram below shows examples of both.

πŸ“¦ Example:


[END OF BOOK]