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 process of compilation and the benefits of statically typed programming languages.
- Determine the static type of an expression involving one or more operators, method calls, and/or implicit/explicit type coercions.
- Visualize the state of the runtime stack in a program involving multiple method calls and/or recursion.
- Describe how Java stores and references objects in memory and how references are aliased across method calls.
- Use the Java documentation to locate a method for a desired behavior and successfully incorporate that method into a program.
- Draw a memory diagram that visualizes instantaneous state of one or more objects.
- Write Java programs involving arrays, utilizing correct syntax for indexing and array literals.
- Write and execute code in Java that utilizes program arguments.
- Develop methods in Java from their specifications that incorporate one or more (possibly nested) control structures such as
if-elsestatements,forloops, andwhileloops. - Develop recursive methods in Java from their specifications.
- Identify and explain errors in buggy Java code both with and without a computer.
Software Development
- Identify the pre-conditions, post-conditions, and side effects of a method and use these to write detailed Javadoc specifications.
- 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.
- Differentiate between black-box and glass-box testing and identify scenarios where each is appropriate.
- Identify the loop invariant of an iterative method involving an array and visualize it using an array diagram.
- Use an array diagram to develop an iterative method that maintains the visualized invariant.
- 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, discussing aspects such as time/space complexity and pre-conditions.
- 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.
- 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. Evaluate the appropriateness of encapsulation in provided code.
- Compare and contrast interfaces, abstract classes, and (concrete) classes, and determine which is most appropriate for a given use case.
- 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. - Suggest and/or carry out a refactoring on a piece of code, and explain how it improves the code's maintainability.
- Trace through the execution of a code sample that includes one or more of the following: inheritance, overridden methods, and
supercalls. - Explain the concept of immutability and its relation to the
finalkeyword in Java. - Contrast the
==operator and theequals()method, and determine the appropriate one for a given scenario.
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 the behaviors, memory utilization, and performance of ordinary Java arrays and Lists backed by dynamic arrays and linked chains. Determine which is preferable for a given use case.
- Draw node diagrams to visualize linked data structures. Implement methods on linked data structures.
- Describe the use cases for the
IterableandIteratorinterfaces. - Implement
Iterators for a given data structure class and use iterators as a client. - Describe the iteratee pattern and identify a scenario where it may be preferable to using an iterator.
- Identify and define functional interfaces and implement them using lambda expressions.
- Describe the semantics of Stacks and Queues, and utilize them within programs.
- Describe composition relationships and scenarios where they may be preferable to inheritance.
Tree Data Structures
- Identify parent, child, root, leaf, ancestor, and descendant nodes in a tree.
- Given a tree, identify its size and height along with the depth and arity of its nodes.
- Write and analyze 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.
- 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, and utilize them in programs.
- Compare the efficiency of Set implementations backed by arrays, sorted arrays, (balanced) binary search trees, and hash tables.
- 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.
- Contrast hash collision resolution by chaining and linear probing. Identify scenarios where each implementation might be preferable.
- Implement data structures backed by chaining or probing hash tables.
Graphs
- Identify substructures in graphs such as neighborhoods, paths, and cycles both visually and programmatically.
- 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 vertex as either undiscovered, discovered, visited, and/or settled.
- 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 observer pattern and use it to write event listeners for graphical applications.
- Explain the execution of a Swing application and its use of the event dispatch thread.
Concurrency
- Describe advantages and disadvantages of concurrent code.
- Use Java's
Threadclass 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 synchronize modifications of a shared resource and incorporate them in concurrent programs.