CS 2110 Learning Outcomes
The following is a list of skills that you will have after taking this course. This list is not meant to be exhaustive, and some topics may need to be reduced or omitted based on our pacing during the semester. A lot of the outcomes use terminology that we will introduce during the course, so the list is likely most useful in retrospect.
Foundations
- Explain the difference between statically and dynamically typed programming languages.
- Determine the static type of an expression involving one or more operators, method calls, and/or implicit/explicit type coercions.
- Draw memory diagrams that visualize the state of execution of a program involving multiple method calls and/or recursion.
- Explain how Java stores and references objects in memory.
- Use the Java documentation to locate a method for a desired behavior and successfully incorporate that method into a program.
- Draw object diagrams to visualize reference types.
- Write Java programs involving arrays that utilize syntax for indexing and array literals.
- Write and execute code in Java that uses program arguments.
- Develop methods in Java from their specifications that incorporate one or more (possibly nested) control structures such as
if
-else
statements,for
loops, andwhile
loops. - Develop recursive methods in Java given their specifications.
- Identify and explain errors in buggy Java code both with and without a computer.
Software Development
- Write detailed JavaDoc specifications for a method given its signature and an English description of its behavior.
- Describe the client and implementer roles in software development.
- Identify the pre-conditions, post-conditions, and side-effects of a method given its specifications and signature.
- Incorporate defensive programming practices such as pre-condition checks and invariant assertions into code.
- Write comprehensive unit tests for a method given only its specifications and signature.
- Evaluate the coverage of a unit test suite on a method or a class.
- Explain the process of test-driven development and identify its potential benefits.
- Describe the differences between black-box and glass-box testing.
- Describe the loop invariant of an iterative method involving an array and visualize it using a diagram.
- Use an array diagram to develop an iterative method.
- Write precise specifications for methods involving arrays that use range notation.
- Explain exceptions and their relationship to specifications and defensive programming.
- Write code that throws, propagates, and handles exceptions.
Complexity Analysis
- Explain the benefits of using asymptotic analysis versus performance testing to evaluate the efficiency of a piece of code.
- Determine the asymptotic time and space complexity of a piece of code involving one or more loops and/or method calls.
- Determine whether a given (mathematical) function belongs to a given big-O complexity class.
- Compare and contrast linear search and binary search.
- Determine the number of recursive calls and the maximum depth of the call stack of a recursive method and use these to compute its time and space complexities.
- Compare and contrast the insertion sort, merge sort, and quicksort algorithms, discussing aspects such as time/space complexity and stability.
Object-Oriented Programming
- Given the description of a class, identify its state and behaviors and use these to sketch its fields and public method signatures.
- Identify the invariant of a class and write code that maintains this invariant and/or asserts that it is satisfied.
- Compare and contrast static and instance methods.
- Write an instance method given its specifications that accesses and/or modifies the values of its object's fields.
- Draw memory diagrams that visualize the state of code involving instance method calls.
- Determine the scope and lifetime of a variable.
- Explain the object-oriented principle of encapsulation and its benefits. Identify examples of proper and improper encapsulation in provided code.
- Compare and contrast interfaces, abstract classes, and (concrete) classes.
- Implement an interface using a given state representation according to its specifications.
- Compare and contrast static types and dynamic types.
- Identify three scenarios where subtype substitution is permitted.
- Explain the benefits of leveraging polymorphism in object-oriented code.
- Describe the principle of dynamic dispatch and the compile-time reference rule.
- Explain inheritance relationships and their benefits/drawbacks over interfaces.
- Given a parent class, use inheritance to develop one or more child subclasses.
- Determine the correct visibility modifier (
public
,protected
, orprivate
) for a given field or method and justify your choice. - Trace through the execution of a code sample that includes one or more of the following: inheritance, overridden methods, and
super
calls. - Determine whether a class is mutable or immutable.
- Explain the semantics of the
final
keyword. - Describe the semantic differences between the
==
operator and theequals()
method, and determine the appropriate one for a given scenario. - Identify the requirements of the
equals()
method specified in theObject
class and override this method in user-defined classes.
Linear Data Structures
- Describe the differences between data structures and abstract data types.
- Implement a generic class or method with one or more generic type parameters. Use generic classes in client code.
- Describe the semantics of auto-boxing and auto-unboxing and identify where they happen in a code snippet.
- Implement abstract test suites for an ADT utilizing the template method pattern.
- Compare and contrast the behaviors of ordinary Java arrays and dynamic array types such as Java's
ArrayList
. - Compare the performance of a List implemented with a dynamic array and a List implemented with a linked chain. Determine which is preferable for a given use case.
- Draw object (or node) diagrams to visualize linked data structures. Implement methods on linked data structures.
- Describe the use cases for the
Iterable
andIterator
interfaces. - Implement
Iterator
s for a given data structure class and use iterators as a client. - Describe the iteratee pattern and how it differs from using an iterator.
- Identify and define functional interfaces and implement them using lambda expressions.
- Identify use cases for the Stack and Queue data structures.
- Describe composition relationships and scenarios where they may be preferable to inheritance.
Tree Data Structures
- Identify parent, child, root, leaf, ancestor, and descendent nodes in a tree.
- Given a tree, identify its size and height along with the depth and arity of its nodes.
- Write recursive methods on general and binary trees.
- Given an image of a binary tree, write out the pre-order, in-order, and post-order traversals of its nodes, and vice versa.
- Implement iterators on trees.
- Describe the binary search tree invariant and determine whether it is satisfied by a given tree.
- Describe the use cases for the
Comparable
andComparator
interfaces. - Explain the semantics of generic type bounds and write code that incorporates them.
- Write modifying methods on a binary search tree that preserve its invariant.
- Analyze the time/space complexities of a given method on a binary search tree.
- Describe the invariants of a heap and determine whether they are satisfied by a given binary tree.
- Translate between the tree and array representations of a heap.
- Implement operations on a heap and determine their time/space complexities.
- Use a heap to implement a priority queue and analyze its performance.
Advanced Data Structures
- Describe the operations of the Set and Map ADTs.
- Write programs utilizing Sets and Maps.
- Compare the efficiency of Set implementations backed by arrays, sorted arrays, (balanced) binary search trees, and hash tables.
- Use functional interfaces to implement operations on data structures.
- Use a Map to implement a dynamic priority queue and analyze the space/time complexities of its operations.
- Identify the steps of hashing and describe the properties of a good hash function.
- Visualize the state of a hash table after performing a given sequence of operations.
- Describe the differences between hash tables that use chaining and probing for handling collisions. Identify scenarios where each implementation might be preferable.
- Implement data structures backed by chaining or probing hash tables.
Graphs
- Translate between a formal description (list of vertices, edges) and an illustration of a (weighted) graph.
- Describe adjacency list and matrix representations of a graph and compare the space/time complexities of operations on each of these representations.
- Perform BFS and DFS traversals of a given graph by hand and in code.
- Visualize the state of a graph traversal at a given point of its execution, describing each node as either undiscovered, discovered, visited, and/or settled.
- Describe the relationship between DFS and topological ordering.
- Describe Dijkstra's shortest path invariant and use it to establish properties on the unvisited portions of a graph at a given point in the execution of Dijkstra's algorithm.
- Implement Dijkstra's shortest path algorithm and analyze its time/space complexities.
Event-Driven Programming
- Categorize aspects of a GUI application as part of its model, view, or controller.
- Write code to set up the component hierarchy of a graphical application given a mock-up of its design.
- Describe the work performed by a layout manager and its interaction with elements in the component hierarchy.
- Use the Java documentation to find and incorporate new GUI widgets into graphical applications.
- Write code that performs custom painting on graphical components.
- Describe the inversion of control in event driven programs.
- Write event listeners in graphical applications.
- Explain the execution of a Swing application and its use of the Even Dispatch Thread.
Concurrency
- Describe advantages and disadvantages of concurrent code.
- Use Java's
Thread
class to write concurrent code. - Identify race conditions in a given piece of concurrent code and list the possible states the program can be in after it executes.
- Explain the semantics of locks in Java and write code involving synchronization.
- Describe the conditions that can cause deadlock in a concurrent program and how it can be avoided.
- Explain how condition variables can be used to synchronize modifications of a shared resource.