Complex and simple programming tasks

Show Full Version

Each of us has our own ideas about what learning should be like. They are based on past experiences, other people's stories, and certain ideals. These perceptions often differ from how the process of becoming a good developer actually works. Students may feel that they're being taught incorrectly or burdened with unnecessary knowledge. Everyone's had an experience like this at school or university. Hexlet is no different. In this article, I'll explain some theoretical basics of the learning process and give you a different perspective on what is going on around you. This will help you to improve your learning and cope with difficulties more easily.

Programming learning without continuous real-world coding is practically useless, no one doubts that. Therefore, despite many YouTube learning videos and articles from blogs or books being available, people enroll in schools and buy hands-on courses. On the other hand, the assignments on these courses can be structured so differently that it becomes a determining factor in how students learn.

There are two extremes in how practical assignments are organized. The first is to give assignments that are solved by almost exactly repeating the code taught in the lesson. The second is to give assignments that require deep, independent immersion into the subject. These two extremes by themselves are rare, usually, the particular assignment falls somewhere in between. Some schools are closer to one edge of the spectrum than others. Which approach is better? Where's the balance?

Programming has one distinctive feature that sets it apart from other fields. Let's take cooks as an example. Good chefs know a lot about produce, cooking methods, storage, and ensuring the right conditions (hygiene & sanitary rules). They can wield knives proficiently and do their tasks many times faster than you or I could. That said, most cooks follow ready-made recipes to make something. Only a small fraction of them are capable of creating new dishes on their own, and there is little need for it. It's the same story in many other professions, where the level of decision-making is very limited. In such places they follow prearranged instructions.


Programming is not like that. Even at the most basic level, programmers are like chefs who need to create their own dishes, guided by the taste preferences of food lovers (the customers). On a daily basis, almost any non-trivial project will be accompanied by dozens of complex decisions: from database design to interaction with payment systems (billing) and interface organization. All this requires not only a lot of varied knowledge, but also the ability to synthesize new things, find simple solutions to complex problems, cope with technical limitations, and spot hard-to-find mistakes.

You can't prepare for this in advance, you have to spend a lot of time learning and getting your hands dirty. Almost every situation programmers encounter is unique. Yes, we stand on the shoulders of giants and use ready-made libraries and frameworks, but this does not exempt programmers from implementing the application logic that will do exactly what we need. The larger the application, the more complex the implementation. You have to take a huge number of factors into account, talk to a lot of people and make compromises.

In real life, a programmer spends most of their time doing four things (if we talk about coding only):

All of this has a direct impact on how learning works. Tasks where you repeat after the teacher, without making a serious effort, create a false sense of understanding of what is going on. As a rule, people don't gain anything from such a learning. Students feel this themselves, especially when they have to do something on their own without any guidance. And, of course, this approach bears no resemblance to the real world. These people are not ready for real problems.

Why, then, is this method quite popular? Mostly because this kind of learning is easier to sell to people and retain them (up to a certain point). Users themselves subconsciously expect to understand everything, because they paid money, so backing out would be expensive (and it's easier to get all your answers at once).

The other extreme is much closer to real life. Challenging assignments make you understand the topic, read additional literature, try different algorithms, make mistakes, and eventually get the result. But on such assignments, a large proportion of people will lose motivation and simply go for the easy option. Some will be disappointed in themselves and think they're not capable of becoming a programmer. So overly complex tasks are almost as bad as simple ones.

Think back to school. Who was your best teacher? How did your teacher's strictness affect the quality of your learning?

Thousands of people study at Hexlet every month. Throughout the years of educational activity we've had a lot of time to analyze which assignments work better or worse, and find the balance that, on the one hand, won't kill motivation and, on the other, encourages independent learning. We think we found it (but have not yet implemented everywhere, as there is a lot of content).

The main conclusion we drew was that the level of independence should be raised gradually (this is not the same as the level of difficulty). Ideally, the initial learning should be as simple as possible, along the lines of "repeat after me". This will give you confidence and lay the groundwork. At this level there is a focus on structure and syntax. That's why we made a separate project for complete beginners https://code-basics.com. Short lessons, each one illustrating just one concept. For example, there are more than 6 lessons devoted to calling functions on CodeBasics alone. For someone just starting to learn programming, f(10) and f(x + 5) are completely different things, which should be explained sequentially, allowing you to write simple code as often as possible.

It should be added that learning something completely new is always different from expanding on an area where you already have some knowledge. This happens because the beginner doesn't even have the basic patterns in their head that would help them navigate the topic. For example, when a beginner stumbles on a mistake, they may spend a lot of time dwelling on it, waiting for the solution to come to them. An experienced developer, on the other hand, starts to act immediately: they read the text, type it into Google, search on StackOverflow, turn on debugging mode and find their answer, not through over-thinking, but through experimenting and debugging.

On Hexlet, the level of task difficulty and independence will increase right from the beginning. On the one hand, tasks become more complicated algorithmically, requiring time for analysis and a bit of ingenuity. On the other - students are encouraged to find additional literature, libraries, and functions, examples of which were not fully covered in the course (but links are always provided). Although, technically, there are no new concepts or syntax in these examples. Their solutions are based on the covered theory. This is where the study of the language structure ends and the real thinking begins - forming the working models to solve complex situations.

Next, in projects, we start incorporating elements from real coding: working independently with the environment, GitHub, and build systems, as well as dependencies, the command line, and architecture design. The further into the projects, the more noticeable it becomes. At the end of the last projects, topics are given that were not dealt with at all in the theory, but our students are ready for (we gradually build up to the fact that you have to be able to work independently) and, as a rule, they handle them well.

This approach is based on several important assumptions:

Our general goal, in addition to specific knowledge, is to teach the student to cope independently: googling, reading documentation, debugging (this is an art in itself), understanding the source code, and analyzing tests. This is all reflected in the structure and how we work with users in the community. Hexlet mentors very rarely give a straight answer to a question, as these hinder students rather than helping them (although many do not realize this - a consequence of treating schools as a service). This, by the way, is not easy; many people expect straight answers and get very annoyed when they are spoken to "in riddles". The only way this can change is to become aware of the learning principles through articles like this.

A slight (or heavy) feeling of irritation toward the teacher is not only normal but is most likely an indicator that everything is going well (except if you dislike the teacher himself because of some personal qualities). Learning something new is almost always a painful process.

Despite all of the above, no one is safe from mistakes. Even despite our extensive experience with offline learning, it took us many years before we knew how to teach programming online effectively. Moreover, even understanding this, we realize that it's impossible to create the perfect course in advance. The online audience, unlike the student body, is completely unpredictable. On platforms like Hexlet studying completely different people with different experiences, learning levels, and attitudes toward the process. That's why feedback is so important to us. Constructive feedback is the only way to understand where we went wrong, didn't explain the theory well, made the exercise too easy or hard, and so on.

Conclusions