A proactive programmer studying data abstraction should demonstrate the mastery of the following learning objectives in the categories of data structures, rigorous programming, and effective communication. According to Robert Talbert, a learning objective must be "a clear, measurable action that a student should be able to do once the lesson is over".1 For the purposes of this site, these learning objectives are not for a specific lesson but rather an entire course for either an Allegheny College student or, for the duration of self-paced learning, all other emerging proactive programmers.
A person learning data abstraction with the mindset of a proactive programmer will be able to demonstrate mastery of the following skills in data structures:
- Correctly implement and/or use a data structure, such as a stack, list, or dictionary, ensuring that it provides all of the functionality required by the program's specification.
- After importing an existing implementation of a data structure (e.g., a list or a dictionary), confirm that it provides the required functionality and integrate it into an existing program.
- Adapt an existing implementation of a data structure so that it offers additional and/or different functionality not provided by that structure's standard implementation.
- Leveraging knowledge of existing data structures like a list or dictionary:
- Specify the input, output, and behavior of functions for a new data structure.
- Design, implement, and document all functions of a new data structure.
- Implement, execute, and maintain a test suite for a new data structure and demonstrate that, for a particular input, its behavior matches the specification.
- Integrate the new data structure with the data structures used by an existing program.
- Document the trade-offs associated with the implementation of the new data structure, comparing and contrasting it with existing alternatives and justifying the need for the bespoke implementation instead of those that are already available.
- Use the principles of object-oriented programming (i.e., encapsulation, inheritance, and polymorphism) to design, implement, document, and test classes that provide all of the features required by the specification of a data structure and the algorithms that process it.
- Use exception handling techniques to ensure that the implementation of a data structure does not inappropriately crash when it runs in non-standard execution circumstances.
- Given input from the file system, network, or console, input the data values, store them in a data structure like a list, and then implement and use a sorting algorithm like merge sort to order the list of values. Using the same list of values, implement and use a search algorithm that can either find a specific value in the list or confirm that the value is not in the list.
- Given input stored in a data structure and solution constraints, use a technique like dynamic programming to solve an optimization problem (e.g., the 0/1 Knapsack Problem).
- Given the psuedo-code description of an algorithm that processes and/or manipulates a data structure, perform the following steps as part of its analytical evaluation:
- Characterize the number of basic operations in both iterative and recursive algorithms.
- Use the asymptotic notation and the characterization of its basic operations to classify an algorithm as belonging to a well-known worst-case time complexity class.
- Using an algorithm's worst-case time complexity, compare and contrast it with other algorithms that have similar and different time complexities, explaining which algorithm is most appropriate depending on, for instance, the likely size of a program's input.
- Describe ways in which it is possible to re-design an algorithm and the way in which it processes a data structure so as to improve its worst-case time complexity.
- Explain how an algorithm exhibits trade-offs between its worst-case time complexity and the amount of space that it needs to store the data structure.
- Given the Python-based implementation of a data structure and the algorithm that processes and/or manipulates it, perform these steps as part of its empirical evaluation:
- Implement a benchmarking framework that repeatedly executes an algorithm through a doubling experiment in which the size of the input repeatedly doubles.
- Use the benchmarking framework to run a doubling experiment for an algorithm, computing the doubling ratio for execution time at each stage of a benchmark.
- Use the computed doubling ratio to experimentally predict the likely worst-case time complexity class to which the data structure and algorithm belong.
- Leveraging both the likely worst-case time complexity and the experimental data reported from the doubling experiment run by the benchmarking framework, describe ways in which it is possible to re-design the algorithm to improve its performance.
- Using the likely worst-case time complexity and the experimental data, explain how an algorithm trades-off between time efficiency and the space needed for data storage.
- For the implementation of a data structure and its associated algorithms in the Python programming language, use the results from both the analytical and empirical evaluation to:
- Confidently classify the algorithm according to its worst-case time complexity.
- Identify strengths and weakness in terms of both time and space efficiency.
- Suggest ways to improve the efficiency of the Python implementation.
- Given one or more sets of textual, numerical, categorical, and/or combined data that describe the performance of an algorithm or data structure, implement, test, use, and evaluate functions that perform data analysis through these steps:
- Input, process, check, and clean the data sets to confirm their correctness.
- Run an appropriate statistical technique (e.g., the calculation of a mean, median, or standard deviation) to summarize and analyze the performance data.
- Use an appropriate data visualization technique that can create graphs and/or diagrams that highlight the salient properties of the data set (e.g., show the general trends in the data set while drawing attention to the dispersion of the values).
- Use statistical analysis and data visualization techniques to surface trends in a data set.
- Implement and use an appropriate data processing method that transforms the data into any format required by any external functions (e.g., convert from JSON to CSV).
A person learning data abstraction with the mindset of a proactive programmer will be able to demonstrate mastery of the following programming skills:
- Write short Python functions of ten to twenty lines that have the following characteristics:
- Has function and variable names that adhere to an industry-standard coding style.
- Has descriptive comments for module definition and both the function's declaration and the function's code that adhere to an industry-standard coding style.
- Features a source code format that adheres to an industry-standard coding style.
- Passes an automated test suite, written with an industry-standard framework such as Pytest, showing that it correctly implements the specification for the function.
- Has an automated test suite, written with an industry-standard framework such as Pytest, that covers at least the 80% of the statements and branches in the function.
- Performs the specified operation in an efficient fashion, as determined through experiments that record the function's performance in seconds or milliseconds.
- Correctly uses assignment statements, iteration constructs, conditional logic, function invocation, and function recursion in a way that passes the function's test suite, works efficiently, and conveys the intended function's purpose in a Pythonic fashion.
- Correctly uses a data structure like a dictionary in a way that passes the test suite, works efficiently, and conveys the intended purpose of the data structure.
- Correctly performs file and console input and output, ensuring that all input and output is displayed and stored correctly, is not corrupted, and is processed efficiently.
- Correctly performs calculations for statistical properties of a data set (e.g., the mean, median, and standard deviation), while also clearly displaying the data, its relevant summarization values, and the interpretation of all statistical properties.
- Write correct Python programs consisting of between one and five hundred lines of source code that correctly solve problems using data structures like a list or dictionary.
- Uses the features of the Python programming language to create classes and instances of these classes that solve problems by using object-oriented programming.
- Implement and run Python programs with the following environments and tools:
- Python programs with dependencies, packaging, and tasks, managed by Poetry.
- Python scripts without external dependencies that are run with the interpreter.
- Jupyter notebooks run through either Jupyter Lite or Google Colab.
- Python code segments run in a read-eval-print loop (REPL) on Jupyter Lite.
- Use a Python programming environment to complete these tasks while implementing a Python program consisting of between one and five hundred lines of code:
- Install, upgrade, and use Python 3.8, 3.9, or 3.10 programming environment to create, run, and debug a Python program through a terminal window and/or a text editor.
- Use Poetry to install a Python program's dependencies, create a virtual environment, and run it without error in an isolated and self-contained configuration.
- Use and create a test suite implemented with Pytest to detect a failure in a Python program and then effectively use tools like a text editor and a terminal window to find and fix the fault, ultimately confirming that the Python program no longer contains the fault and that the fix did not compromise other functions in the program.
- Use a text editor like VS Code to implement, test, debug, document, and manage the source code of a Python program, leveraging plugins for workflow enhancement.
- Use the GitHub platform and the Git version control system in the following fashion:
- Clone a GitHub repository without error using either a command in a terminal window or an extension for Git integration in a text editor like VS Code.
- Write short and descriptive commit messages that explain the specific way in which a commit changes the source code and documentation in the GitHub repository.
- Navigate reports produced by GitHub Actions so as to determine which aspects of a GitHub repository do and do not adhere to a project's specification.
- Use the GitHub Flow model to implement specific features in a branch of a GitHub repository and then merge that branch to the main one only after all the checks run by GitHub Actions pass as required and code reviews confirm the code's correctness.
- Create and discuss programming and technical writing issues through the use of the GitHub Issue Tracker and the GitHub Discussion Forum, furnishing descriptive titles and problem descriptions that adhere to industry best practices and project templates.
- Submit completed projects that pass all of the instructor-provided and industry-standard checks, as evidenced through the report of a passing build by GitHub Actions.
A person learning data abstraction with the mindset of a proactive programmer will be able to demonstrate mastery of the following technology-mediated communication skills:
Follow a systematic process when using resources to implement Python programs:
- After detecting an error in a Python program through the use of tools like GatorGrader or Pytest, develop a satisfactory understanding of the problem's possible root cause and then search sites like Stack Overflow for potential solutions.
- After evaluating suggested solutions to a programming problem that originate from sites like Stack Overflow, develop a way to fix an error in a Python program.
- Independently develop solutions to Python programming problems even if the specific technical challenge that you face was not previously covered in a course session or as part of your prior review of technical content.
Use Discord to effectively communicate about technology in the following fashion:
- In the correct public channel, post a question that includes source code segments, screenshots, and a description of the steps taken in an attempt to solve a problem.
- Answer questions that were posted in a public channel, responding with source code segments, screenshots, and links to external references, pointing the proactive programmer who asked the question in the right direction without solving the problem for them and limiting their opportunity to learn more about the topic in question.
- Proactively offer to help others who may need to learn scientific, mathematical, or technical knowledge and skills that a learner has already mastered by sharing the acquired knowledge or skill, how you can be contacted, and how you can best assist.
As Robert Talbert explains, a learning objective is clear when it is "clear from the students' perspective" and measurable when there is "some way to know whether the objective has been met" or "how far away the learner is from meeting it". Do you see a way in which we can improve the learning objectives for data abstraction? If you do, then please participate in the proactive community by sharing your ideas for improving them!
See Robert Talbert's article entitled How to Write Learning Objectives for more details about how to design learning objectives for an academic course. From your perspective what does it mean to write learning objectives that are both clear and measurable? ↩