[PYTHON] We held an in-house study session on mob programming with the theme of FizzBuzz.

This is @aimof from iRidge Inc. I have hosted a mob programming study session within iRidge (mainly for young people), so I will summarize it when I report it. This time, I used the general code (FizzBuzz) instead of the production code. This article is a rewrite of a document shared internally by IRIDGE.

Purpose of study session

Internal purpose

Personal purpose

Mob programming atmosphere

Since we were free to go in and out, there were some fluctuations, but the number of people was about 4 to 5 and we carried out for 2 hours. There are three members who participated from the beginning to the end.

It was good to immediately notice any misunderstandings or mistakes, as everyone other than the driver would have to think with each other with their heads together. (Although there were some bugs that weren't fixed: see below).

I think the members were able to work together with a sense of unity.

theme

Here is the theme prepared this time.

FizzBuzz with additional requirements each time it's completed

basic rule

For numbers from 1 to 100

About adding requirements

Draw one from the requirements prepared in advance and add the requirements.

This time, I decided to put a box and a pen and ask them to write their requirements freely. Various things from basic requirements to difficult ones were gathered.

Result report

From here, I will tell you the atmosphere while writing the actual code.

Ordinary FizzBuzz

for i in range(1, 101):
    if i % (3 * 5) == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        print(i)

No commentary required? It's an ordinary FizzBuzz.

Requirement 1: Do not use lowercase f in source code

I gave up.

I pulled it in one shot because it was included as a story. It is very painful because basic syntax such as if, def, for is restricted. Next quickly.

Later, I was told one solution in-house. (It is python2.7)

i = 1
while i <= 100:
    print "Fizz" * (not i % 3) + "Buzz" * (not i % 5) or i
    i = i + 1

Requirement 2: If the last 10 outputs contain 6 or more numbers from 0 to 9, output as ok.

def has_six_different_num(values):
    char_set = set()
    for value in values:
        if type(value) is int:
            for char in str(value):
                char_set.add(char)
    if 6 <= len(char_set):
        return True
    else:
        return False

values = list()
for i in range(1, 101):
    value = ""
    if i % (3 * 5) == 0:
        value = "FizzBuzz"
    elif i % 3 == 0:
        value = "Fizz"
    elif i % 5 == 0:
        value = "Buzz"
    else:
        value = i
    values.append(value)
    if len(values) > 10:
        del values[0]
    if has_six_different_num(values):
        value = "ok"
        values[-1] = "ok"
    print(value)

It has become quite long. The code is already worth refactoring. If you were writing code that would make you say that it's really unpleasant to turn for twice ...

Requirement 3: Speed up. Half the execution speed is a guide

I have drawn the requirement as if I was told to correct the double for statement. Everyone laughed unintentionally at the good timing.

Here are the results.

def has_six_different_num(values):
    return 7 <= len(set(list("".join(values))))


values = list()
for i in range(1, 30001):
    value = ""
    if i % (3 * 5) == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        value = i
    values.append(str(value))
    if has_six_different_num(values[-10:]):
        value = "ok"
        values[-1] = "ok" # <-This is a bug
    if value:
        print(value)

It was quite refreshing. Since it is difficult to speed up with 100 times, the number to be output has increased to 30,000. It has increased from 0.044 seconds to 0.028 seconds.

7 <= len(set(list("".join(values)))) I learned a lot from this part.

Returns true if 7 types of char including the empty string are used.

Actually, this code bug. I just wrote it in the comments. If you do not substitute an empty string here, the two characters of ok will be treated as a number judgment.

Requirement 4: Reverse the output

def has_six_different_num(values):
    return 7 <= len(set(list("".join(values))))


values = list()
for i in range(30000, 0, -1):
    value = ""
    if i % (3 * 5) == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        value = i
    values.append(str(value))
    if has_six_different_num(values[-10:]):
        value = "ok"
        values[-1] = "ok"
    if value:
        print(value)

Just change the range. I haven't noticed the bug yet.

Requirement 5: Run rm -Rf ~ if a Runtime Error occurs

It's gone for my convenience. It's a company computer ... By the way, the Runtime Error never happened after this!

Never run this command. The following home directories are deleted.

Requirement 6: Outputs Foo when it is a multiple of 7, and outputs Bar when it is a multiple of 11. When two or more are the mainstays, the display order is Fizz, Buzz, Foo, Bar.

As I got used to it, the speed at which the driver could guess from Mob's remarks became faster. It seems that the line disappears immediately after saying that I want to erase it.

I forgot to save the code for this requirement, so I will summarize it in the next section.

Requirement 7: Receive natural numbers as standard input and return the results up to that number in a Json array

import json


num = int(input())


def has_six_different_num(values):
    return 7 <= len(set(list("".join(values))))


values = list()
output_values = list()
for i in range(num, 0, -1):
    value = ""
    if i % 3 == 0:
        value += "Fizz"
    if i % 5 == 0:
        value += "Buzz"
    if i % 7 == 0:
        value += "Foo"
    if i % 11 == 0:
        value += "Bar"
    if not value:
        value = i
    if type(value) is str:
        values.append("")
    else:
        values.append(str(value))
    if has_six_different_num(values[-10:]):
        value = "ok"
        values[-1] = ""
    output_values.append(value)
print(json.dumps(output_values))

This is the final result. The bug has also been fixed.

Summary and impressions

It was a study session (trial session) for mob programming, but to be honest, I enjoyed it more than I expected. This time, I wrote a code with a strong event nature, so I think that the feeling that everyone was crazy was stronger than usual.

However, we also received feedback that we would like to use the production code if there is a next one. It's fun to prepare the code that is in trouble at IRIDGE and use it as a material for study sessions. (The problem is that you can't publish the code on Qiita)

What I felt as a merit of mob programming

In addition to the original purpose, it was a big merit that I could not do anything appropriate because it led to my own thinking.

Other summary

I think it was good this time that the requirements will increase. The reason is that it is developed small and refactoring is very important.

Personally, I would like to have an even more interesting study session within iRidge. If we have an interesting study session, we will publish it on Qiita again!

Recommended Posts

We held an in-house study session on mob programming with the theme of FizzBuzz.
Read "Ordinary Linux Programming" at an in-house study session
I tried studying on the WEB server side at an in-house Python study session
Read "Ordinary Linux Programming" at an in-house study session ~ 10.11 Exercises ~
An example of the answer to the reference question of the study session. In python.
An easy way to pad the number with zeros depending on the number of digits [Python]
A Study on Visualization of the Scope of Prediction Models
Create a shape on the trajectory of an object
The basics of building an in-house server for Linux (CentOS 8.1, openSUSE 15.1, Ubuntu 20.04)! File server with Samba