Beginner tips for programmers

Guest contribution by | 16.09.2021

As a programmer, you should cultivate one thing above all: Laziness. This doesn’t mean that you shouldn’t put all your effort into something, or that you shouldn’t spend your entire annual holiday on your new idea. Rather, it means that you should save yourself work when programming and reuse, improve and adapt components where you can. This will save you time that you need for the more complex problems and make for a more structured way of working and better code.

Moreover, laziness is the best idea generator for new applications or new features. The computer itself probably wouldn’t have come into existence in the first place if people hadn’t been too lazy to do tedious calculations by hand. Higher programming languages like C++ wouldn’t have come into being if people hadn’t been too lazy to enter byte code character by character. And Netflix would not have existed if its founder had not been too lazy to return rented video tapes on time.

After this slightly ironic introduction to the mindset of a successful programmer, I would like to give you some tips for getting started in programming or C++ development. It’s about two concrete and very useful Clean Code principles, research, testing and practical tools. Let’s go.

The development of clean code

Clean code refers to code that is easy to understand, change, extend and maintain. It is the result of values, principles and successful practices of software development. Programming is not about mastering challenges extra cleverly, in an individual way, better and smarter than all other programmers would have solved a problem. At first glance, clever code sounds positive, but it is a synonym for a superficially clever way of developing software, which, however, is not recommended for professional programming.

I would like to briefly introduce two of the 19 principles of clean code:

DRY: Don’t Repeat Yourself

As a programmer, try to repeat yourself as rarely as possible. Having similar code in several places cannot always be avoided, but should always be considered carefully. At the latest when you have three similarly written places, you must consider whether the part can be outsourced to a separate function or a class. I always ask myself the question “If I later have to fix a bug in this place, how high is the risk that I forget the other, similarly written places?” It saves you a lot of work.

KISS: Keep it simple and stupid

The KISS principle is a guiding principle that is not only helpful in software development. “Keep it simple and primitive” means to prefer the simple solution to the complex one when solving a difficult problem. Sounds obvious, but especially as tinkerers and hackers you are often so easily fascinated by complicated solutions that you overlook the pragmatic way. The best example of this is unfortunately only an urban legend and untrue, but it hits the nail on the head nonetheless: during the space race, NASA had discovered that normal ballpoint pens would not work in weightlessness and therefore developed a special biros for one million dollars. The Soviet Union, on the other hand, had simply used pencils. So the art of solving difficult problems is not to overlook the simple solutions.

When developing for software, the KISS principle is particularly important, because software changes. Sure, when you have finished a programme that solves your problem satisfactorily, you might not care if you have programmed it in a particularly complicated and convoluted way – the main thing is that it works! In reality, however, it is rarely the case that a programme is finished and then never changed again. As soon as you are allowed to add a new functionality or do some bug-fixing a few months later, an over-complex implementation becomes your undoing.

Unfortunately, the question of what exactly is and is not unnecessarily complex programming is not trivial at all. The question of how to design a particularly good software architecture and how to implement the above principles fills entire books¹.

Internet research as a source of knowledge for programmers

Malicious tongues claim that a programmer is a machine that converts coffee into code. Even more malicious tongues claim that a programmer is a machine that converts coffee into internet search terms. There is certainly some truth to this, as the sheer volume of programming forums and open source projects means that there is a wealth of freely available knowledge on the internet.

Note: The vast majority of sites for programmers are in English, so it helps a lot to switch Visual Studio to English: Tools → Options → Environment → International Settings. This will output compilers and other errors in English and make them easier to research.

In many cases you will come across articles from Stack Overflow, an online forum for asking and answering programming questions. Unfortunately, especially with C++ questions, you have to accept that this language is very formalised and the answers are therefore sometimes written in a very mathematically accurate way. In my opinion, a little more pragmatism would help, but you get used to it. Maybe at some point you will see some unanswered questions for which you could write an answer yourself – the site thrives on exchange!

Furthermore, the pages https://gitlab.com/explore and https://github.com/explore are true treasure troves of open source projects in a wide variety of programming languages. If you want to look at code from other programmers, you will find it here. However, this can get really complex very quickly, and you will come across some concepts that I am excluding here in my explanations.

Software testing with unit tests

Programmers make mistakes. Fortunately, you can use technical help to track down these errors. Besides using the debugger or self-written logging classes to analyse bugs, you can also write automatic tests that find bugs before your customers do. Even better – whenever you have fixed a bug, you can write an associated automatic test that ensures that the bug will not occur again in the future.

There are dedicated libraries for writing automatic tests and whole books dedicated just to this². Also, there are certain types of bugs for which an automatic test is very costly – for example, display bugs or bug handlers themselves. Therefore, I would like to give you just a tiny insight into a special kind of testing here, namely unittests.

Unit tests mean that you divide your programme into the smallest possible units and test them individually. For example, you take each function, pass it a few parameters each and compare whether the result corresponds to the expected value.

Let’s write a “self-test” for this, which simply runs as part of our programme. This should give you a feel for how to proceed as a software tester. In this example, the implementation of the factorial() function is tested:

UnitTest.cpp

#include <iostream>
#include <vector>
#include <exception>

int factorial(int number)
{
if (number == 0)
{
return 1;
}
return number * factorial(number - 1);
}

void unitTests()
{
// Test-Code für die Berechnung der Fakultät
const std::vector<int> tests = { 6, 0, 1 };
const std::vector<int> expected = { 720, 1, 1 };
for (int i = 0; i < tests.size(); i++)
{
int actual = factorial(tests.at(i));
if (actual != expected.at(i))
{
std::cerr << tests.at(i) << "! ergab "
<< actual << ", erwartet wurde "
<< expected.at(i) << std::endl;
throw std::exception("factorial() is broken!");
}
}
}

int main()
{
unitTests();

int number;
std::cout << Zahl zwischen 0 und 12 eingeben: ";
std::cin >> number;
std::cout << std::endl << "Fakult\204t: " << factorial(number)
<< std::endl;
return 0;
}

In the unit test, especially the edge cases (0 and 1 in this case) should appear. As you can see, here the test is always executed at the beginning of the programme. In reality, of course, these tests are separated from the actual programme and executed separately only on the developers’ computer, not on every end user of the programme. But if they can be executed as quickly as in this example, there is nothing to be said against them for the sake of simplicity.

If you have gained a little experience with unit tests, I would recommend turning the whole thing around: Test-Driven Development is the name of a method where you write the automatic test first and only then the function or class that was tested.

  1. Write the body of the function or class to be tested. Define all input and output values, but leave out the implementation for now. If a return value is needed, return a dummy, for example: int sum(int a, int b) { return 0; }.
  2. Now write the test that passes certain values and compares the result with the expected values.
  3. When writing the test, you will often notice that your original concept was not complete. By using the code in a controlled environment, you may notice that the calls are too nested or that you want to have more helper functions (which of course you also want to test).
  4. After everything has been corrected, run the test. It should fail, because the function/class is not yet properly implemented. This is another important point, because this way you make sure that your test can really find a bug (Test the test!).
  5. Now you can get down to the actual implementation. After that, the test should pass.

 

Further tips and tools

In this short section, I would like to provide you with some more food for thought and keywords that you can research further if needed. The subject area is huge.

There are countless different methods for the development process. Agile software development, for example based on Scrum, is relatively widespread and modern. It is based on the realisation that in a software project, the planning phase and the development phase cannot be strictly separated. Since not all requirements are determined at the beginning of a project and some aspects only emerge during implementation, it makes no sense to carry out a planning phase lasting several months and then spend a year programming largely without customer feedback. Instead, after an initial, short planning phase, you move as quickly as possible into development, but then repeat and update the planning regularly. So-called sprints of two or four weeks are common here, which begin with a planning meeting in which the development goals for the sprint are recorded.

Requirements are often formulated in the form of user stories. These stories should be collected in a central place and made available to the team. For this you need a so-called ticket system. In my view, Trello or GitLab are very suitable. In these or similar tools, you can also store bugs, i.e. the description of programme errors that have been found but not yet fixed.

Document the following information in the bug report:

  • In which software version does the bug occur?
  • What steps can be taken to reproduce the bug?
  • What result would I have expected?
  • What result did I get?

Another point is to work together on the same code. A version management programme makes it possible to exchange code via a server. As soon as a new function is implemented or a bug is fixed, the programmer uploads the change with a short description so that it is automatically merged with the changes of the others. My recommendation here is Git.

Lastly, you need a tool for sharing messages. Emails quickly become confusing, so I recommend setting up an online forum or using a team-oriented chat service such as Slack or Element.io. The only important thing is that you can organise conversations into threads and they are easy to find again.

 

Notes:

[1] E.g. Clean Architecture – Das Praxis-Handbuch für professionelles Softwaredesign by Robert C. Martin
[2] E.g. The Art of Unit Testing by Roy Osherove

This article is an excerpt from the new book “C++ Schnelleinstieg – Programmieren lernen in 14 Tagen” by Philipp Hasper. All information about the book, the table of contents and a free German sample can be found here at mitp, the specialist publisher for IT, business and photography.

C++ Schnelleinstieg - Blog - t2informatik
Philipp Hasper

Philipp Hasper

Philipp Hasper is the founder of an augmented reality start-up and experienced in the academic and industrial development of AI technologies. He develops with C++, Java, Python and Typescript and has contributed to numerous open source projects.