In the last lecture, we saw how to define functions in C++ and how they provide an abstract interface (with typed parameters and return value) over a concrete implementation. With this as our fundamental unit, we'll now turn to the effective use of procedural abstraction, including organization of larger codebases into modules, precise interface specification, and unit testing to ensure correctness.
Because this is a shorter lecture, we'll also take some time at the end for some frank discussion about the use of generative AI tools in EECS 280, especially some data on learning outcomes and grades for students who use them in course projects (notwithstanding the fact doing so is against course policy).
|
1: Procedural Abstraction
Switching gears a bit, let's take a look at the high-level organization of a program using procedural abstraction to make our code easier to write, understand, and maintain. |
|
2: Header Files, Makefiles, and Project 1
2.1
As projects grow more complex, we often need to split the code into several different modules. In C++, we often use use a We'll use project 1 as an example to illustrate each of these. First, we'll look at the role of function prototpyes and header files. Now, some discussion of the overall structure of project 1 and the
2.1 Exercise: Interface vs. Implementation
Categorize each of the following according to whether they are part of the interface or implementation (write "interface" or "implementation" in each box). Function declaration in Function definition in Code inside the function's curly braces Which input values are valid or invalid for the function Comments inside the function to clarify tricky lines of code RME comment before the function declaration in Sample solution… Function declaration in Function definition in Code inside the function's curly braces Which input values are valid or invalid for the function Comments inside the function to clarify tricky lines of code RME comment before the function declaration in |
|
3: RMEs for Interface Specification
It's useful to adopt a common patten for comments that specify function interfaces. In EECS 280, we'll use RMEs:
|
|
4: Unit Testing
4.1
Finally, let's take a bit of time to talk about unit testing. We need to make sure the code we write actually works. In particular, we'll look at unit testing as a strategy for making sure that the implementation we write for a function actually works according to the interface we've decided for it to have. We'll look at some examples and general strategies for writing good tests.
4.1
Which of the following are true statements about unit tests? |
|
5: Generative AI in EECS 280
5.1
Finally, a miscellaneous but important topic - the use of generative AI tools to write project code in EECS 280. The quick version: don't do it - you won't learn as much and your grades may reflect this. But, the long version is worth hearing. And we've been hard at work collecting some pretty fascinating data to back it up. Before moving on, I want to reiterate that the use of generative AI tools to write any significant portion of your project code is prohibited by EECS 280 course policy. So don't interpret the discussion above as "at your own risk", but more as "it's not allowed, but I also won't pretend it doesn't happen and I want to let you know what we're seeing".
5.1
Which of the following appear to be plausibly true based on our data + analysis of generative AI usage in EECS 280 projects? |