After receiving feedback and API tests from your colleagues, your task is to finish the implementation of your library while adhering to design and coding guidelines presented during lectures. In the second half in the implementation period, you will have to give a short presentation on the progress of your implementation (which is officially task #6).

Integrating API tests

The API tests from your colleagues been pushed to separate branches matching the api-testing-* pattern. The branches originate at the point of export represented 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 the branches into your project (and delete them afterwards).

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 no README.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 that README.md and the reference documentation serve different purposes. You can keep README.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 in form of methods that do 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.

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.