The goal of this task is to finish the implementation of your library while adhering to design and coding guidelines presented during lectures. You will have to integrate API tests from your colleagues and give a a short presentation on the (almost final) state of your library (which is officially task #6).
Integrating API tests
The API tests from your colleagues will be pushed to separate branches
matching the checkpoint/api-testing-*
pattern, originating at the
export commit marked by the task-4-export
tag. You will find a
diffstat
output for each set of tests (or a note indicating a missing
test suite) in the .nprg043/tests
directory. You should merge both
branches into your project so that they will become a part of the
library before final review.
When integrating the tests into your project, keep them in separate source directories, but do run them together with your own (unit) tests.
Implementation checklist
When finalizing the implementation, please pay attention to the following checklist which emphasizes some of the things that are typically checked during the final review (both by students and the course instructor):
Overview documentation
- Typically found in
README.md
(it is very disappointing if there is noREADME.md
or if it is (almost) empty – treat it as something that conveys the first impression of your project). - Provides high-level overview of the project and key concepts, and shows basic examples corresponding to common use cases, so that a potential user can get started quickly.
- When referring to specific classes, link to the reference documentation (in the location where the project build system puts it).
- Enumerates direct dependencies and provides a summary of build-system operations, i.e., how to build the project and run tests, and how to build the reference documentation.
- Provides links to additional resources, e.g., reference documentation or any other documents.
Build system, one-touch testing, and CI
- Ensure that your project is automation-friendly, i.e., it must be possible to compile it without an IDE, even if you use IDE extensively.
- Code in our master branch (the one you will be submitting) should always compile and require only a single command to build, run tests, or generate documentation.
- Keep a CI configuration so that each new commit can be automatically tested.
Reference documentation
- Provides detailed description of the public API and documents the most important design decisions with respect to typical use cases. The idea is that a user should be able to understand the logic behind your design.
- When mentioning specific classes, link to their reference documentation.
- Provide a reasonable description for each public method. A description that just adds space between words in a camel-cased method name is not considered reasonable. Think roles, contracts, etc.
- Be meticulous in describing aspects of the contract provided by a method, the range of valid parameter values, and behavior in case of errors.
- If your library is extensible, describe the extension mechanism and its intended use, ideally with an example.
- The reference documentation is typically generated from source code and
you should make this process as simple as possible (one touch). If the
process of generating documentation is too involved, do provide a
pre-generated archive in your submission.
- This specifically applies to DocFx, which is painful to use on the Linux platform. Try using Doxygen instead: it just works. Keep in mind that it is the content that counts, not how fancy it looks.
- The title page of the generated documentation must not be empty. You can
reuse some of the introductory content from
README.md
, but keep in mind thatREADME.md
and the reference documentation serve different purposes. You can keepREADME.md
rather simple (key concepts, API style, tutorial) and point to the reference documentation for more details to avoid duplicating content.
See also some extra slides on documentation (Czech).
API design
- This is the last opportunity to change your API. At this point, you are not expected to make sweeping changes (such as switching between declarative and imperative API), but you can still make your API easier to use or avoid frequently discussed problems.
Implementation
- Strive for self-documenting code (it lets you document private parts of your code less verbosely). Key aspects of self-documenting code are good names for values and behavior, i.e., variables, fields, and methods.
- Use private methods (or functions) extensively to break code up into smaller (named) blocks and use them to compose more complex behavior in higher-level methods. If you see a block of code with a comment, consider turning it into a private method that you call. Not doing this is a common issue that costs points.
- Make data flow between methods explicit and avoid accessing data in “global” manner, even within a class. This often manifests as methods that do not accept any parameters and return no values. In a broader sense, this also applies to accessing instance data (fields) from private methods deep in the call chain. It is usually better to pass the data into worker functions from higher-level functions.
- Keep related things together and use scoping diligently to avoid making
your internal APIs visible to the user. Common mistake is to use packages
(in Java) or namespaces to classes of the same kind together, e.g., putting
exceptions into
exceptions
subpackage or namespace. To make effective use of package-private scoping (or similar concept in non-Java languages), you should only have one package for one unit of reuse. This will allow you to only expose API classes and keep a lid on the rest. - Avoid string and numeric literals in the implementation code — use symbolic names instead.
Code formatting
- Pick a style and stick to it, consistently, throughout the whole project. Even better, configure a tool to format the code for you.
- Use white space to separate logical blocks of code within classes and within methods. Not doing so results in all code being squeezed together, which makes it difficult to read.
- Use white space around operators (unless they are unary) and around keywords. In general, think of the code as prose, where you need to be able to easily distinguish words and paragraphs.
See also some extra slides on code formatting (Czech).
Please keep in mind that the list is far from exhaustive and that you should generally try to stick to the various guidelines presented during lectures, unless there is a good (and documented) reason for not doing so.
Use of generative AIs
Using AI assistants is discouraged, but not prohibited. In general, you may use AI to improve your own work but not to do the work for you.
Paraphrasing an excerpt from Ethical use of AI: Guidelines for Caltech applicants: If you are wondering where the boundary is, ask yourself whether it would be ethical to have, e.g., a teacher perform the task (you are asking of the AI) for you. Would a teacher be able to review your code and suggest improvements? Of course! Would that same teacher write most of the code for you to tweak and then submit? Definitely not.
That said, you MUST disclose any use of AI along with a summary of how it has been used (to help shape the policy on AI use in the coming years).
Submission
When you are satisfied with your solution, make sure it is in the master
branch of your task-1
repository and tag the commit using the
task-5-submission
tag. The code will be then exported for final review.