Software Construction: Data Abstraction Flashcards

1
Q

To build a call graph

A

look at all the method calls in a method definition and draw a line on the graph from the method to each method it calls.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Hypothesis driven debugging

A

making careful educated guesses, with plans for how to validate or invalidate them.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

If you notice a value (or field) is showing up as wrong, then

A

there are three typical problems to check: you’re not retrieving the value correctly, or you’re not setting the field correctly, or you’re not setting it at all.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

If you are changing a parameter’s value inside a method, and aren’t seeing that value reflected once the method has returned

A

check to make sure you’re not just changing a local variable instead of the object referenced by the parameter.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

If you’re looking for an object based on some field, and not finding that object,

A

make sure you are comparing against the field values, rather than accidentally comparing object references. (We will see an even more elegant way to do this in the second course)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

An exception’s stack trace message

A

tells us where the execution died (in the method at the top, right below the message)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

An index out of bounds exception means

A

you tried to access off the end of a collection. Remember to check whether you are in range (likely by using the collection.size() method) before accessing a collection.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

A null pointer exception means

A

you tried to execute a method, or access a field in an object that has not been instantiated. Before using an object, it’s best to check if it exists! You can use if (theObject!=null) to check.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Remember to keep checking hypotheses even if you have found your bug.

A

There may be more than one thing wrong.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

There are four phases in our design approach (often applied in a circular way):

A

specification of public interface, usage scenarios, test specification, and finally implementation.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Specification means

A

determining exactly what the public operations should be, and what they should expect/assume when called (REQUIRES), what they change (MODIFIES) and what they produce (EFFECTS).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Usage scenarios means

A

looking at all the ways that your abstraction will be used – this will perhaps motivate new operations, which will then need to be specified

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Test specification means

A

writing a thorough and rigorous test suite for every operation prior to implementation

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Implementation involves

A

deciding on an internal representation of the data in the abstraction, and then implementing the public and supporting private methods to make it work. The tests should all pass when the implementation is done

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

a REQUIRES specification of a method indicates

A

the preconditions of running that method.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

typically we do not include trivial preconditions (such as the parameter must be non-null), but instead focus on

A

conditions of correct running of the method.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

If a method can be called regardless of the state of the program, then

A

no REQUIRES clause is needed.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

mutability means that we can

A

set the value of an object and it will remain changed. We saw this with variables earlier in this course.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

The MODIFIES clause indicates

A

whether a method, or any method it calls, mutates any object.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

If a method mutates its own object, we indicate that it MODIFIES:

A

this

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

If a method mutates another object, we indicate that it modifies

A

that other object.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

If A.a() calls B.b(), and B.b() specifies that it modifies this, then A.a() would specify that it modifies

A

B.

23
Q

If nothing is modified in a method, or any method it calls, then we

A

do not include the MODIFIES clause in the specification.

24
Q

The EFFECTS clause indicates

A

the purpose of the method – describing the work that the method does.

25
Q

For public methods, this clause EFFECTS only describes

A

publicly visible effects – implementation details are not described.

26
Q

Effects clauses for private methods have

A

more flexibility in their level of detail, but typically also only indicate “publicly” visible effects – however these might mention internal details of the class implementation more freely than the specification for public methods (because a developer of the class is reading these specifications, not a user of a class).

27
Q

Thinking through usage scenarios involves

A

considering all the situations in which another class would make use of the data abstraction we are creating. We want to think through not just the operations that are available, but the order in which they will be called. This, in turn, helps us make sure we have all the methods we need.

28
Q

To sketch out usage scenarios

A

create a main function (IntelliJ shortcut: psvm) either in a new class, or an existing class (typically we make a new class for this purpose).

29
Q

Into that main function

A

place calls to the data abstraction in all the arrangements and combinations you can think might be valid. Think through every situation in which the data abstraction will likely be used, and make a little usage scenario for that combination. These scenarios do not have to be as exhaustive as the test scenarios we will do in the next part. Instead they should capture the spirit of the usage of the data abstraction.

30
Q

Test driven design (typically a part of agile software development) involves

A

writing tests right after writing your specifications, then implementing your code until the tests all pass.

31
Q

Tests are a more comprehensive way of

A

checking the conformance of your implementation to its intended specification.

32
Q

Black Box Testing is a way of testing software

A

without knowing any of the internal structure or implementation details of the system being tested. In this case, we are interested in testing the functionality of the software.

33
Q

White Box Testing is a way of testing software

A

that actually tests the internal structure and implementation details of the system. In this case, we are no longer interested in testing the functionality of the software – rather, we want to test the actual details of implementation.

34
Q

A test suite is the

A

collection of test cases that, together, thoroughly (though not 100% exhaustively – that’s impossible for all but the most trivial cases) test the data abstraction.

35
Q

Create a test case for everything happening in the what clause?

A

effects clause, and create a test case for each combination of inputs and outputs.

36
Q

Create tests such that

A

each branch of your method is followed (this is loosely related to branch coverage, though at this stage we are just checking branches generally, since we do not yet have an implementation against which to design a test case with proper branch coverage)

37
Q

Write test cases to test the edges of

A

ranges (boundary checking) to check for typos in range checks or conditional statements.

38
Q

Test case should be named after the

A

method they are testing, and also after the scenario they are testing to help you keep track of what you have tested. (Test)

39
Q

Test cases always specify

A

the inputs, and the expected outcome

40
Q

Name test classes “Test” and then

A

the name of the class you are testing

41
Q

Each test is basically structured:

A

(1) set up,
(2) call the method to test,
(3) check that the expected outcomes occurred.

42
Q

Pull duplicated lines of set up declaration code into

A

fields.

43
Q

JUnit looks for the @Test annotation to

A

identify methods to call as tests

44
Q

@Before (JUnit 4) or @BeforeEach (JUnit 5) lets you

A

annotate a set up method that will be run before each test method. The annotated method does not need to be called from within the test methods – it runs automatically.

45
Q

Pull all duplicated lines of set up behaviour into

A

that @Before/@BeforeEach method.

46
Q

AssertTrue, AssertFalse and AssertEquals can also be used to

A

check the state of objects and values. If any of these fail, the test fails.

47
Q

Conditions can be used to check values or states of an object to check that it has been modified correctly – and if it has not,

A

the Fail keyword can force the test to fail.

48
Q

JUnit is a mechanism for type of testing

A

black box testing: testing abstractions from the outside

49
Q

Writing tests with JUnit

A

For each test case, we write a method in our Test class, and annotate it with @Test (that will cause IntelliJ to add either JUnit 4 or JUnit 5 into the classpath – either is fine for this course)
We write the set up code for each test, and put it in the set up method, and annotate that method with @Before (or @BeforeEach)
Then we write comments to indicate the 3 parts of the test: (1) check that the set up is correct, (2) call the method to test, (3) check that the outcomes were expected. Write these comments as specifically as possible for what you are testing.
Checking the setup involves checking that the work expected by the method has not already been done. Sometimes this can be intuited, but typos creep into code, and especially if more than one person is collaborating, behaviour can suddenly pop up anywhere. Best to check that the set up is clean.
Calling the method to test is straightforward. Sometimes this is integrated into the next stage, if you are directly checking the output of the method. Other people like to save the output of a method, and then check it one a separate line of code. That might make it easier for troubleshooting later.
Checking the expected outcome involves looking at the outputs of the method and writing conditions or assertions that will fail if the outcome is not correct.
Remember: A test will pass unless you make it fail, so having a passing test isn’t a great accomplishment. You should have a correctly passing test!

50
Q

Breakpoints can be set in tests, just like in “regular” code. Sometimes it is helpful to

A

pull calls to methods into their own line of code, rather than placing them inside assert statements, so that you can more easily isolate them for breakpoints.

51
Q

A problem with the branching in complicated conditional statements often causes

A

bugs in code.

52
Q

If a test is failing when you believe it should be passing (or the reverse), you

A

may be asserting the wrong thing. Typos often creep into assert statements.

53
Q

Remember to properly structure your test so that it is setup - call method - check outputs. If you mix these up

A

the logic of the test may not be well formed, and the test may pass or fail when it should not.

54
Q

Deciding which method to call (which implementation to use) is called…

A

method dispatch.