TR 9:15 - 10:30 am (CAS) 134
Week 12 Class 22 Tue Nov 11 Posted: Nov 11
Announcements
No New Rules
The questions I receive about Project 3 TDD are almost always in the form of general, written hypotheses, such as:
From these rules, it looks like whenever both a URL and a hash are provided, the URL should take priority in determining the final attribute values. And if the disk filename conflicts with either of those, does the priority system always override it? I want to verify whether this hierarchy is intended to be absolute across all inputs.
What is happening is that students are trying to state explanations/new rules. This, in general, is not useful. We already have the rules. We do not need an annotated version. Besides, I have to work to understand what you really mean, and I am often unsure that I understand correctly.
What I rarely get is a test case where the student wants to know if they have the correct output.
This is useful. I can answer this easily.
This applies to much more than this problem. Instead of asking if your wordy, difficult-to-understand interpretation is correct, create the test and ask about that. We already have the problem of difficult-to-understand original rules. Don't make it worse.
Mock Clock III 360000 or 3600 I do not know what these numbers mean. In a large project, how would I remember this?
or even
What I can easily understand is:
So why not use this formula? Why did I see people using a calculator for this. The C++ compiler (and the compiler for almost any real language) can compute this at compile time. Why not take advantage of this?
Why is this important? Because we need to find things in our code. And if you were looking for 100 hours, you would search for the value 100. And when you use cryptic things such as 360000, that doesn't work. Write the program as much as possible using concepts from the problem domain. This includes naming, literal values, strings, etc. Here is an adapted example from the Linux kernel:
So write these clearly as factors. Let the compiler do the math.
Redirecting an Output Stream
Testing the output of code to std::cout (standard output) or std::cerr (standard error) is not immediately testable in a unit test. We need to "grab" this output and store it in a std::string so we can verify the result. The way to do this is to redirect the output to a string. The following program is an example of how to do that:
Class
Unless stated otherwise, all exercises are due by 3 pm on Wed Nov 12
In this exercise, you will go through a workflow to perform a refactoring. The overall process includes:
There is no report or uploaded notes. The following workflow must be followed to receive credit. Use the exact commit messages as shown.
main, you are going to work on the branch issuen where n is the issue number, e.g., if the issue number is 1 then the branch name is issue1. First, make sure you are in the branch main. Then, create the branch:
Branches can be created via GitHub. However, please create this issue via the command line.length() definition to the new method size(). Successfully build the program. Once done, commit using the commit message:
Push your changes to GitHub.size() and length() do the same thing. Now, change length() (the old method) to call size() (the new method). The definition of length() should only have the call to size(). Note that you must pass along the parameters and handle any return statements. Once done, commit using the commit message:
Push your changes to GitHub.length() with a call to method size(). Again, this must be done one call at a time. After each change, compile, build, and run successfully. Commit each time using the commit message:
Push your changes to GitHublength() in ToDoList.cpp. Compile, build, and run successfully. Once done, commit using the commit message:
Push your changes to GitHubAt this point, the refactoring is complete.
Create a pull request at GitHub. You want to pull from the branch issue1 into the branch main.
Accept the pull request at GitHub. Typically, this would be done by another team member, but in this case, you can accept your pull request.
Switch to the main branch in your cloned repository and pull the changes. The rename should appear in the code on the main branch.
issue1 has done its job and is no longer needed. All your commits on this branch are now in the branch main.To implement the project below, follow the TDD process. The Brightspace course page has an invitation link to create the GitHub Classroom repository.
Create your repository (via GitHub classroom) and implement each one of the Rules separately with a single pass through the TDD workflow (red, green, refactor). Each rule (and error message) is implemented in a single commit.
Due Dates
The purpose of many class exercises and projects in this class is to practice good workflows of actual, real, 40-hours-a-week software development. Due to time limitations, each part of a project cannot be very long. Treating this as a "race" at the last minute is not part of SE or any good workflow. It tends to produce less-than-optimum software in both external quality, i.e., bugs, and internal quality, i.e., poor design.
Therefore, the project has progressive due dates regarding the number of rules implemented. Each failure to meet a due date will result in a 10-point reduction in your score out of 100. The following are due dates, not the day you have to work on them, unless you wait until the last day.
| No. | Due Date | Total Rules Implemented | Exercise Feedback |
|---|---|---|---|
| 1 | Monday, Nov 3 11:59:59 pm | 1 | 43 |
| Stop Wait until I provide feedback on your initial workflow by giving you a score for the corresponding exercise. If you don't see a comment, I have not examined your first commit. If you are waiting to continue, send me an email. | |||
| 2 | Wednesday, Nov 5 10:00:00 pm | 2 | 45 |
| 3 | Thursday, Nov 6 10:00:00 pm | 3 | 49 |
| 4 | Friday, Nov 7 10:00:00 pm | 4 | 50 |
| 5 | Monday, Nov 10 10:00:00 pm | 6 | 51 |
| 6 | Tuesday, Nov 11 10:00:00 pm | 7 | 55 |
| 7 | Wednesday, Nov 12 10:00:00 pm | 8 | 56 |
| 8 | Thursday, Nov 13 10:00:00 pm | 9 | |
| 9 | Friday, Nov 14 10:00:00 pm | 10 | |
| Monday, Nov 18 11:59:59 pm | All rules and all error messages |
Due dates are given for each step. No work will be accepted after the last due date.
All commits must appear in the repository on GitHub. Commits or code changes in GitHub Codespaces do not count.
The input for a source-code static analysis tool can come from multiple sources, including individual files, e.g., main.cpp, directories of source-code files, e.g., src/, source-code archives, e.g., project.tar.gz, file.zip, and standard input, i.e., stdin, e.g., std::cin. In addition, solitary files and source-code archives can include a URL, e.g., https://mlcollard.net/fragment.cpp
To perform the code analysis, the source code is wrapped in a single XML element with metadata about the source code, including filename, programming language, URL, hash, LOC (lines of code), and timestamp. For the source code:
the resulting XML is:
Note: Scroll to see all the attributes.
The attribute hash is of the source and is a SHA1 160-bit (20 bytes) represented in 40 hex characters, which is what Git uses. The xmlns:code="http://mlcollard.net/code" is not an attribute but an XML namespace declaration, handled automatically by XMLWrapper.
The general attribute rules are:
The attribute's variety of input sources and program options follows the Rules stated below.
Implement the following rules following a Test-Driven Development (TDD) approach. Write a test in CodeAnalysisTest.cpp, implement the minimal code necessary to get it working in CodeAnalysis.cpp, refactor/clean up the code to make it clear and logical, and then commit with an appropriate commit message.
All commits must result in a program that compiles and passes all tests. This means you must successfully compile and pass the test program before a commit. Any commit that does not build will result in a 0 for that step, and every commit will be checked.
The following rules are unordered. Do not refer to them by number.
std::cin) of non-archive source code, the disk filename is a single dash "-" and the entry filename is the literal string "data". In this case, you must use the option filename for the attribute filename.std::cin) of a source-code archive, the disk filename is a single dash "-". In this case, use the entry filename for the attribute filename.All error messages are written to standard error (i.e., std::cerr) on a separate output line, and the function should return an empty string.
The workflow for implementing one rule:
All implementation should result in code that is as clean and clear as possible. For this case:
std::string_view to std::string."", use the empty() method.The project is built and graded in a Docker container running srcml/codespaces, which is the same environment as GitHub Codespaces for this project. It is based on Ubuntu 24.04 and uses the GCC compiler.
On macOS, clang is the default compiler and the one you want to use in most cases. This should not cause a problem with this program. However, before you commit, I recommend ensuring your code can build and pass the tests with GCC and the default compiler, clang.
Add GCC via homebrew:
brew install gcc
The preset macos-gcc (in the file CMakePresets.json) provides settings to compile with GCC:
cmake .. --preset macos-gcc
This preset only appears in macOS and not in Linux or Windows.
To return to using clang:
cmake .. --fresh
Instead of flipping back and forth in the same build directory, use two build directories, one for clang and one for GCC. Be sure to build and test in both build directories before you commit. Note It might seem like a pain to have two build directories, but it is not uncommon in real software development and is a good skill to have.
Your score will depend on the following:
TA: Mr. Sumaila Iddrisu si63@uakron.edu