"Mad tea party" — an experiment for teaching students the rules of good code

We — math camp "Elephant" — has long run summer and winter schools for students grades 8-11. The main activity at school — work on the major task of the project. This can be anything from simulation of complex physical systems to program against encryption or writing toys under Android. Most of the projects at the school are somehow connected with programming, but programming is rarely an end in itself of the project. Students who had not yet become hardened programmers, and even in the context of the eternal shortage of time to write code "Schaub worked." So we know firsthand what the bad code and every year we meet more and new, sometimes surprising even us, ways to make code unreadable — and every year deciding what to do with this problem.

For example, last year we do code-review task opening tasks. However, our code-review is voluntary: we tell the students on mistakes, but not forcing them to rewrite the code (less efficient, but more humane). This idea seems to us good, although it takes a lot of time at the inspection.

Another idea was to use git "to the nonsense of everyone was visible". Then towards the end of the project could be reviewed, how it all began and where turned, terrified to do otherwise. However, this idea has not passed the test of time. In our experience, students difficult to learn to use version control system, but still regularly. They do not understand, what SLE is needed, but because they are bored. In addition, to take just a couple of hours on mastering git mad extravagance for the project length is one week. And not for the version control system was originally conceived.

The solution that we used this winter we ourselves loved, so we consider it necessary to share your method. We named it "Mad tea party".
So, the task: to teach students to write clear and neat code. Thus it is necessary to make this process fascinating...

To learn to write good code, we usually look for examples of good code and bad code. Students usually only look at your own code. The course is designed to change this practice: participants look at good code and bad, and write the code yourself. Children usually act as criticism on the course was the opportunity to look at someone else's code, criticize it themselves, and try to improve. How?

We took the same task, the terms of which can vary significantly (for us it was Koniavska the game of Life) and broke it into smaller steps. The split is made so that at the end of each iteration gets ready running program. The stages themselves are quite small, so for one session (length 1.5 hours) can be completed, sometimes 1.5 hours fit even two iterations.
Future iterations of the participants are unknown in advance, so that's where "put a straw" for the current iteration to make the next iteration was easy, it is also unknown.
At the beginning of the students given the task of the first stage. After it was completed by all participants, it was time to "move". Participants shared solutions and got the job the second stage. Now they had to understand someone else's code and modify it so that it solved the problem of the second stage. In this case refactor the code and correct the mistakes of others was allowed, but to rewrite code was completely prohibited. After the second stage, students again exchanged solutions and continued to write code, and again on the base. Communication between participants in the course are limited, so to find out "what the hell is written here", could only get a grasp of the code. Between iterations was conducted debriefings recurring stylistic errors that have been prescribed to correct.

On our course there were five students and, accordingly, five projects. Over each file in different moments of time worked three student. When after a few iterations they came up when your own code, it is already very different from what they originally wrote. Someone else's code with which they worked at the previous iteration they were more "his" than native code, which came to them after going through all the other participants.

But let us with the details so interesting. As I said, the global task was to write Konovsky the game of Life, but this task was previously unknown. Specify the stages were as follows:
    the
  1. Write a one-dimensional game of Life (aka elementary cellular automaton), the playing field size of 200 cells. Cell survives or is born if it has exactly one neighbor. For the extreme points "neighbor" abroad are always "dead". Initially, fill the field with living cells so that the numbers of living cells constitute a geometric progression with ratio 2. Every move is by pressing the Enter key.
  2. the
  3. Allow the user to enter the size of the field and the coefficient of geometric progression. Added the ability to enter the command "W" to do not one but 10 steps.
  4. the
  5. allow the user to specify the initial field configuration: the user enters a number, its binary representation, specifies which cells are alive (bit 1) and which is dead (bit 0). Also need to check that the initial configuration set fits in the specified field size. Add the command "R", which restarts the program.
  6. the
  7. Change the rules of survival now survival of the cell with one neighbor, and arises out of nothing, if there is a neighbor on the left. Supplemented by the option "W" so that it was possible to enter a number of steps that the field must do.
  8. the
  9. Rules of life are now given a number from 0 to 255 for each of the eight initial configurations (the Central cell with two neighboring, each in two positions) is set to one bit: what should be the cell in the next step.
    by the Way, this modification of "Life" you can guess
    Excerpt from the school newspaper:
    "Mad tea party" predicts the fate of the one-dimensional the game of "Life": enter age as a rule — look at the development of cells. Received these are very plausible results: in 16 years, and then everything is hopelessly bad, and everything is constantly go in the sunset; in 23, finally, there comes stability; sometimes you can still live, to be together. The editorial staff — the expert on the game of "Life" adds that in 25 this divination predicts the reproduction of that characteristic. Universal knowledge, as we know from lectures, come to 110.

  10. the
  11. Added saving and loading of fields and rules.
  12. the
  13. Move the game into a two-dimensional world. Now the rules are defined in a standard way: the number of neighbors to survive and the number of neighbors to rise; the status field is set line by line.


All the students we wrote in Python, but programming skills of the participants is quite different. The format of the field is such that the difference of the level of the group is not a minus, but a significant plus. Use a common programming language is useful but not required. It is possible that the use of multiple languages will make the course even more exciting, because in real life, sometimes you have to read and edit code in an unfamiliar language.
We are not forced students to use a version control system, they themselves brought the materials into one repository. Quite a fascinating read for those interested in learning programming.

For all normal people those who do not want yourself poking around in someone else's code, will guide your observations and analysis of errors: how errors the students and our own.

Code exchange between participants is extremely well smoothed, the quality of the code base. Even if you started a program with many single-letter variables and lack of modularity, then a couple of iterations, someone is bound to give variables good names, file structured, simplified code. And to spoil someone else's (relatively) good code — it is necessary to try; easier to integrate into someone else's style. In addition, students pick up each other (or teacher?) any patterns. Sometimes, the good.
However, contrary to our expectations, over time the code became more and more dissimilar. Once the decisions have continued to live and grow, though, and fell into the hands of people who themselves have done differently. However, in fairness, it was not always so. To some participants it was hard to accept the fact that someone solved the problem differently, and they sat down to rewrite in their own way normal working pieces of code... And not always did it better. And variable names were as changeable as their content. Apparently, it is necessary to introduce some formal limitations on the scope of changes.

According to the author of the course, the best "Mad tea party" influenced students of the middle level, and less on the weakest and the strongest student. The weakest always comes very decent by his standards code, and very strong, not someone to look up to. To improve this situation, if the instructor of the course will participate in writing code, as an additional two participants. The first such party will be writing to refactor and change the code as if I would write it myself, and the second is to artificially make bad code worse than the weakest member.

I must say, some of our students well know how to write in OOP-style. And therefore, quite remarkable that they didn't use it, even where the PLO arises. It seems that for them the object is not the obvious choice when it comes to simplify the code. It is not enough to learn how to write your own classes that should be taught, in some cases, the use of classes will allow to improve the program. In future incarnations of the course should take this into account.

As I mentioned, the names of variables and functions cause edit wars. It seems to me, is not just about taste preferences, but also to the fact that many of the names were quite unsuccessful, and the good names has been successfully established. All my experience of teaching programming says that beginners (even fully grown beginners) do not know how to name the variables meaningfully, because they can not describe what this variable holds.

One reason for this misunderstanding is the idea of a variable as a "box" into which you can put value, read the value and change the value. The name "variable" suggests that they were created to value has varied, and clearly describe the meaning of the object, which at different points in time holds different content — not so easy. Sometimes it is simply impossible. The use of the same variable is probably useful in high-performance applications in low-level (and then only if the compiler does optimizations), but in the modern world this is not the most meaningful use of the language. Usually it's some harmless little conversion: added to the line a couple of characters, I rounded the number converted a string to a number. For example, to the field, added two dummy cells at the edges, and recorded in the same variable. And now, not to say that lies in the variable: a number or its string representation? field or extended field? It seems a trifle, but is the quality of the code. And such trifles are capable to spoil a lot of blood when refactoring.
I am not a staunch advocate of functional programming languages, however, the concept of immutable variables can be very useful for creating habits to good code style.

Another reason is that many are too lazy to focus and articulate the meaning of the variable. Often the name reflects not the contents of the variable and its form. For example, in the third stage have the opportunity to set the source configuration field of the decimal number, which when translated to binary form would a configuration. 4 of 5 programs this variable is called `number` or `decimalNumber`, not `initialFieldPosition` or `aliveCellsEncoded`. Then, these names still changed several times in favor of the tastes of a programmer, but never got finished and logical names. Unlike many other variables, who, once his true name, they stopped throwing. Or here `count_symb`, what is it? In fact, the length of the field — and that field is represented by the string, therefore the number of symbols represents a length of the string.
The third reason is ignorance of the language. Difficult to articulate his thoughts in a language that I do not know. One solution that some use is to issue along with challenge the Glossary of terms on the subject of the task.

With the names of the functions happen in the same edit wars. Part of the reason is similar, but there are specific. The fact that the new code is usually added where it is easier to write, and not where it is logical. If you want to add a function argument or return parameter (remember, we are writing in Python?), he added shamelessly. In successful case, the function name changes accordingly, but not always. After some time, the meaning produced by the function of action is very conventional attitude to her name. What to do with this problem is unclear. One of the options — policy to forbid students to change the type of a function's return value and make a clear division between the functions of producing action and returns the result. However, it is naive to believe that such a ban will work.

Despite all the shortcomings, the course helped students learn to write almost sane code as well as allowed them to experience all the pain experienced by the teacher, reading their programs. ;)

The course of the "Mad tea party" came up and held Pavlo Smyrnov. I just asked the author, read the resulting source codes and recorded their observations.

P. S. Course teaches not how to write the product in advance and carefully think through several steps ahead, and how to work with someone else's code, how to gradually improve it and not give the software to turn into something horrible.
Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

The release of the new version of the module modLivestreet 0.3.0-rc

mSearch: search + filter for MODX Revolution

Emulator data from GNSS receiver NMEA