alexmojaki/futurecoder

Next course chapters

Closed this issue · 16 comments

This issue has been replaced by #92

The biggest thing to do is write the actual course!

This should be an informal, collaborative process. The course doesn't need to be written in the order that it's going to be presented, we can change things as we go, and any amount of brainstorming is useful. Even sharing a little code snippet to demonstrate a concept or a neat exercise is helpful. See below for an example.

If you want to contribute a solid bit of course with actual text, code, and exercises, open a new issue with a proposal just in markdown. Don't jump to implementing it in Python.

Before writing anything, it's a good idea to go through the course to know what's been covered and to get a feel for the style. You don't have to actually read everything or do all the exercises - see the developer mode instructions to skip steps. Reading all the hints on a few exercises would also help.

It can be helpful to read through existing textbooks and such to find inspiration for material. Make sure you have permission to copy their ideas (even if you rephrase it into different words) or that it's permissively licensed. If you're not sure, ask them. I don't want anyone to accuse us of plagiarism.

I'm not sure what exactly the next chapters should be at this stage, but here are some loosely related topics that I want to cover:

  • How to use the birdseye debugger - this will be helpful for understanding and and or correctly. Done
  • Boolean operators and, or, and not - these will be helpful for constructing more useful conditions for if and while. (currently being worked on in #27)
    • Must cover common misuse, e.g. if x == 1 or 2 instead of if x == 1 or x == 2. Birdseye can help here.
  • while. Start with a simple counter (contrast with for i in range), then another example with a proper condition (any ideas for a compelling example?), then while True.
  • Basics of types:
    • Different values have different types
    • These can be revealed with the type() function
    • Types include str, int, float, bool, and list.
    • Different types behave differently, e.g. + and < means different things for each, and each have different methods.
    • Different types are often 'incompatible', e.g. numbers and strings cannot be added, and == is always False.
    • How to convert between types, e.g. str to int and vice versa.
  • input() - goes well with while. Explain that it always returns a string, and must convert to int when needed. Has a volunteer in #61
  • Nested lists

Hey @alexmojaki
I discovered this from your OSSU post.
This is just the kind of thing I was looking for.
I am willing to contribute here and there a little, probably mostly course content.
Here is why:

I attempted to make a similar website in the past but purely focused on Number Theory:
https://number-python.herokuapp.com/
(it's very slow so you'll have to be patient)

It was done as the final project for Harvard's CS50 a few years ago.
At the time I knew nothing about web programming, so it's purely client-side. No logins.
However it does have an Ace code editor and an interactive Python shell.
(Courtesy of the awesome Brython project.)
Though it is very rough and not pleasant-looking.
Also it uses KaTeX to render LaTeX math formulas.
But it works and does some really cool interesting algorithms (like Sieve of Eratosthenes).
It was too time consuming so I eventually abandoned it.

So I would be willing to "convert" some of my own content to your project's format, if I can learn it.
I certainly need your help in that.
I am currently taking Fullstack Open,
so I would be willing to contribute to the code as well, if I can learn it.
(It might be a good idea to write some kind of "developer's guide" after learning it).
My time is spread thin between many other courses and open source projects, so I cannot promise TOO much!

So, TL;DR: currently I have some math content to contribute if you want.
I can also create some content for the basics you listed above, if that's a priority.
Find me on Discord, I am spamegg#3510

Hi @spamegg1! Your project is impressive, well done! It'd be great to have you on the team.

Personally I love maths, but I'd like this course to be appealing and accessible to a wide audience, including people who don't like maths. That's why you'll see that the course content barely touches numbers. So the first priority is the basics above, as you said.

Having said that, I do want to make room for optional mathematical exercises and other detours from the central course - see #21.

I'm going to dump below some rough ideas in the hope of sparking a brainstorming discussion, and also to demonstrate how I think the informal collaborative writing process can start without waiting until you have a polished and ready proposal.

Click to expand

To teach the concept of or, we start with this code that does things the lame way:

print("What is your name?")
name = input()

print("Hello " + name + "!")

if name == "Alice":
    print("I have a friend called Alice!")
if name == "Bob":
    print("I have a friend called Bob!")

Then we show how or allows us to do better:

if name == "Alice" or name == "Bob":
    print("I have a friend called " + name + "!")

Contrast with the common wrong way:

if name == "Alice" or "Bob":

Encourage inspecting what's going on with birdseye, which will need to have already been introduced earlier.

Briefly mention that what or actually does is "if the first thing is false, return the second thing" so that they have some idea why the wrong example did anything at all, but don't dwell on this.

Possible side notes:

  • check can be made more robust to funky input by using .lower() or .strip()
  • Can write name in ["Alice", "Bob"] instead.

Next example (maybe as an exercise):

percentage = 50

if percentage < 0 or percentage > 100:
    print("This percentage is not valid.")
else:
    print("This percentage is valid.")

Show alternative solution using and:

if 0 <= percentage and percentage <= 100:
    print("This percentage is valid.")
else:
    print("This percentage is not valid.")

Possible side note: can write 0 <= percentage <= 100. Should be brief, want to focus on general coding concepts rather than Python-specific tricks.

Exercise: check if a row of tic-tac-toe represents a winner:

row = ["X", "O", "X"]
if row[0] == row[1] and row[0] == row[2]:
    print("We have a winner!")    

Now show how to combine and and or in a complex expression:

row1 = ["X", "O", "X"]
row2 = ["X", "X", "X"]
row3 = ["O", "O", "X"]

if (
    (row1[0] == row1[1] and row1[0] == row1[2]) or
    (row2[0] == row2[1] and row2[0] == row2[2]) or
    (row3[0] == row3[1] and row3[0] == row3[2])
):
    print("We have a winner!")

(probably need to talk about multiline expressions while we're at it)

Exercise: write something similar to check if there's a diagonal winner:

middle = row2[1]
if (
        (middle == row1[0] and middle == row3[2]) or
        (middle == row1[2] and middle == row3[0])
):
    print(middle + " wins!")

Now we suppose the user wants to check if there isn't a winner. We show one way to do this based on what they know:

if (
    (row1[0] == row1[1] and row1[0] == row1[2]) or
    (row2[0] == row2[1] and row2[0] == row2[2]) or
    (row3[0] == row3[1] and row3[0] == row3[2])
):
    "do nothing"
else:
    print("No winner in the rows")

Then introduce not as a better alternative:

if not (
    (row1[0] == row1[1] and row1[0] == row1[2]) or
    (row2[0] == row2[1] and row2[0] == row2[2]) or
    (row3[0] == row3[1] and row3[0] == row3[2])
):
    print("No winner in the rows")

Continuing with this, we could:

  • Talk about nested lists
  • Use loops to solve the same problems instead of a mess of and, or, and indexing
  • Have an exercise to find winners in the columns

Eventually this could feed into the tic tac toe project in #3, although they still have to learn other concepts first.

A high level exercise would be to find a row winner in an arbitrary size board:

def row_winner(board):
    result = None
    for row in board:
        equal = True
        for cell in row:
            if cell != row[0]:
                equal = False
        if equal:
            result = row[0]
    return result

Hi @spamegg1! Your project is impressive, well done! It'd be great to have you on the team.

Personally I love maths, but I'd like this course to be appealing and accessible to a wide audience, including people who don't like maths. That's why you'll see that the course content barely touches numbers. So the first priority is the basics above, as you said.

Having said that, I do want to make room for optional mathematical exercises and other detours from the central course - see #21.

Thanks! Sounds good to me.

It's important to appeal to those who don't like maths, but also important to show them eventually that if they want to pursue programming/CS more seriously, maths is inevitable and they have to learn some. It can be optional, and learned as little or as much as desired.

I've read the above. The stuff about and/or looks pretty good. For the rest I think I need to use the demo more to get a better feel for how the "progression" works. Because in my project I had very clearly defined and separated topics/sections, and it was intended to be done strictly linearly. Later Theorems use earlier Lemmas, etc.

Currently I'm feeling super depressed from the quarantine and the heat, but I'll get back to you after finishing the demo and re-reading.

PS. How do you do the "Click to Expand" thing in Markdown?

if they want to pursue programming/CS more seriously, maths is inevitable and they have to learn some.

I'm not so sure. Personally I'm both surprised and disappointed at how rarely I use any kind of interesting maths or even algorithms when programming actual applications, both for work and for fun. I think it depends a lot on the domain. I'm also not necessarily trying to kickstart careers in programming/CS. Many people could get a lot of value out of just having enough skill to write a short script instead of using a spreadsheet, or being able to read code copied from a website and tweak it slightly to their needs, or just having better problem solving skills and an understanding of what computers do.

Going through the existing course is definitely an important step before writing material.

The expand thing is done like this:

<details>
    <summary>Click to expand</summary>
To teach the concept of `or`, we start with this code that does things the lame way:
...
</details>

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details

Hmm OK. It's important to have that clarification about your target audience and the goals. You are aiming for something a bit lower level than I expected (I don't mean "lower" in a negative way). Since I'm coming from OSSU, there is a reverse problem there: lots of people with practical skills to make applications etc. but no solid knowledge of theory/maths/algorithms.

Ah, so we can use HTML inside Github comments huh? Never used that before.

Just had a few minor nitpicks...

  • The blinking cursor is not on the same line as '>>>', the way it would be in IDLE installed on a user's PC. (This could become crucial much later on with doctest)
  • The position of the interactive shell (bottom right quad of screen) is a bit weird. Most other REPL sites use a side-by-side half/half view. I suppose a debugger/variable display will go on the top right later? Maybe the shell could take up the whole right half of the screen until then? Constantly looking at the bottom of the screen gets a bit annoying. It's more natural for eyes to look somewhere in the middle. Maybe move the shell to top right?

OK... I think I reached the end of the Demo (no more "Next" button). Just to wrap my head around things, and to get into the informal collaborative brainstorming spirit I wrote down what is covered so far:

Topics in Demo

  • Doing some arithmetic in the shell
  • Strings
  • String concatenation (introduces the hint feature)
  • Assign strings to variables (mentions case sensitivity)
  • Undefined variables
  • Concatenating a string literal and a string variable
  • In word + name is word left undefined on purpose? Good pedagogical technique, undefined names are a common issue for beginners.
  • Very nicely catches the lack of space between words.
  • Will there be mention of single, double and triple-double quotes?

OK...

  • I think this can be followed up by your treatment of or, and.
  • I think it's important for a user to type a Boolean expression into the shell and see it return True or False BEFORE jumping into the Alice/Bob code...
  • ...because many beginners confuse assignments and expressions, both involving =. which is sort of an "overloaded" symbol.
  • Since we already covered strings and some arithmetic, just a quick 2 == 3 or 'hello' == 'world' kind of thing should do the job.
  • Then this can be followed by Alice/Bob, and then the percentage stuff.
  • I think it might be a GOOD idea to start introducing a few Python specific tricks. But I won't push you on this point, it's fine if you disagree. I am contributing to some open source Python projects (mostly editing/improving existing code), and there is a lot of non-idiomatic, non-Pythonic spaghetti code written by beginners. They are so easily fixable... it's a real shame. These bad habits are picked up early on and continue for a long time. I'm always thinking long-term...

After this...

  • some basic coverage of lists:
>>> friends = ['Alice', 'Bob', 'Charlotte']
>>> friends
['Alice', 'Bob', 'Charlotte']
>>> friends[0]
'Alice'
>>> friends[1]
'Bob'
>>> friends[2]
'Charlotte'
>>> friends[3]  # some error
>>> friends[-1]
'Charlotte'
  • I'm not sure about the row stuff... it might be a good idea to save that for later, for the tic-tac-toe project, or dive right into that project at this point. Too difficult for now?
  • There should be a very clear indicator to the user "you are starting a project!" and its material should be self-contained, to make the user focus, and give them a strong sense of accomplishment. At least this is how I approached it in mine.

@spamegg1 There's waaaay more course content. Going through it will answer some of your questions.

I've looked at the database, the step you're on says:

Oops...that doesn't look nice. Can you modify the code above so that there's a space between the word and the name?

It's waiting for you to complete that exercise. Do you see something different? Maybe refresh the page?

By the way, an important note for anyone going through the course just to see what's in there and not because they're actually learning Python: You don't have to actually read everything or do all the exercises - see the developer mode instructions at https://github.com/alexmojaki/futurecoder#controls.

@spamegg1 There's waaaay more course content.

Aaaahh... OK! Wow I was being dumb...
The intended solution is word + ' ' + name. I was redefining word or name instead.
I did get a warning after redefining word with a space in it.
I have a feeling some people might get stuck on this.
Also I forgot to use the Hint feature, so I guess there is no way to get "stuck" is there?
Sorry sorry sorry, my bad! I'll finish the rest.

I was trying to locate the code for the content, I think it's in backend/main/chapters.
I like the way you coded up the content; defining classes that can be either a Page or an ExerciseStep.
In my project I had to come up with a similar solution, generating a small script for each interactive step, checking the answer.
So everything up to and including nested for-loops has already been written then?
In that case disregard what I wrote above.
OK, I'll have to keep in mind what the user already knows, to write the next chapters.
One question: will there be "branching out" in the material later on?
So that it's not strictly linear?

You don't have to actually read everything or do all the exercises - see the developer mode instructions

Oh I noticed the "hamburger" button on the top right JUST now.
Feel very dumb once again.
I am using Dark Mode on my browser so it was hard to notice.

@alexmojaki I haven't been able to check the demo, will try later. I am using python for business analytics which means I pretty much have to train each person that comes into my team or that wants to use my tools in my company, so I train a lot of people on python. One reason I have to check futurecoder for me is to see if I can create custom courses. Me and my team have developed a python library for data analytics and I would love to have a standard course for new team mates for instance.

To give you a rough idea of this industry. Enterprise "UI" based tools to do what me and my team do with Python are between $4,000 (Alteryx) and $9,000 (DataIku) per user per year.

@acivitillo I've opened #29 to discuss your question, @spamegg1 I've opened #27 for you. I'm not sure if either of you get notified about that since it doesn't autocomplete your name when I @ in there.

I haven't go through all the excersises, but I would like to propose some of my rough ideas about course contents here. If there are some ideas have already in plan or implemented, please ignore it.

I think it might be a GOOD idea to start introducing a few Python specific tricks

I cannot agree more with this idea of @spamegg1. The conventions of python should be presented to users, e.g. project structure and funtion naming rules. This is important for users to write good-style programs(I was lack of this part of knowledge when I was a beginner). But this could be done later(for we even haven't introduced the concept of function)

For basic knowledge, I think touple and dictionary should be introduced and compared with list. Besides, I don't know if break, continue and pass have been introduced, if not, they can be introduced with loops and if_statements or later with function.

Besides, do you think we should introduce comment first? I think beginners are likely to comment on what they have programed or learned to tell themselves what is it.

I should lay out some of my thinking that has guided a lot of how I have written the course.

I'm trying to appeal to a wide audience, in particular to people who may have trouble learning programming because they lack intrinsic talent or motivation. I'm doing this because if someone already has talent and motivation, then it makes less of a difference how exactly they learn - there are plenty of resources already out there and they will probably figure it out either way. I'm trying to increase the number of people who learn to program by creating a resource that is easier to learn from than most other resources. The idea is that if this site didn't exist, some people would learn from a more difficult resource instead and fail or give up without getting far.

Based on that, I'm trying to cater for people who are lazy and have a short attention span. I'm very much like that myself, but fortunately I love programming! I'm trying to impart that same love to others so that they don't get bored and lose interest. Based on that I try to cover as much interesting content as early as possible, teaching the most powerful concepts that allow writing the most interesting programs. That's why for loops are covered so early on, before even lists or if statements. They let the user draw pretty pictures with just a few lines of code! if statements, by contrast, are extremely useful but a bit boring.

There are a lot of concepts that users should learn about at some point, but I have pushed them down the line because they're just not very interesting. They don't allow the user to do much new stuff that they couldn't do before. Some examples:

  • Allowed variable names. They know that words work, that's enough for now. If they try something else (e.g. something starting with a number or containing a funky character) that's on them.
  • Style, such as naming conventions and whitespace.
  • Tuples. The purpose of tuples is quite subtle. Knowing about lists covers the most important stuff. At the very least tuples should only be introduced after dictionaries, since using them as dictionary keys is the most useful thing you can do with them. Everything else can be done with lists, it's just not necessarily good practice or pythonic.
  • Single, double, and triple quoted strings, and escaping characters in strings. It's a tedious technical detail. I'm fine with students just not knowing how to put a backslash, apostrophe, or newline in their strings for a while.
  • continue is really just a fancy way to save on indentation. There's nothing you can't do without it.
  • pass literally does nothing. It also isn't generally used unless there's a class or higher order function involved. You don't generally use it in a loop or if statement.
  • Same for comments. We also haven't reached the point where students write programs long enough to be worth commenting.
  • enumerate and zip. Students learn how to use range instead because it's more generally useful.
  • Chaining comparisons, e.g. a < b < c.
  • Negative indexing.
  • Slicing.
  • Multiple arguments to range.

I'd love to hear people's opinions and arguments both for and against this idea. I'm sure it's controversial. I want to teach the best way to write code, but I'm also scared of students being overwhelmed or bored.

That leaves a couple of other concepts you've mentioned:

  • break is already covered in the course.
  • Dictionaries are definitely a powerful concept worth learning fairly early on. I haven't prioritised it because at the moment I'm vaguely aiming for students to reach #3 soon which doesn't require dictionaries, but if someone can think of a different first project to do that's also fun and doesn't require too much background, the course might change.

As for me, this idea is kind of similar to the opinion behind the git-learning tutorial pcottle/learnGitBranching and this really interests me. I would prefer to learn something with an interactive tutorial myself, but unfortunately I didn't find one when I learned python.

I have a different opinion on style which you may think a little bit boring, I'm not pushing you to add this though. It's up to you to decide. I think something related to style or conventions is not suitable to be an individual course. Instead, I think it should be included in some of the courses or as appendix. For example, you can design a more complex variable name(I mean something with _, e.g. use your_name instead of name) to use in chapter03. After they have used it, you can simply tell users that python variable name follows the rule like they have used and provide a link for other naming rules if someone has more interests on it. (In fact I think even only using this example without more explanation to reveal this convention to the users is enough. Beginners may imitate the naming convention of the tutorial imperceptibly)

Besides, I haven't dig deep into #3(so this may be similar to what you have planed), but is it more interesting to provide part of it as an excercise to the previous chapters so that when they try to complete it, they can recall what they have done? Will it be more fulfilling to complete part by part?

(I'm not very sure about the idea, just propose my thinking)

I think you have a good idea there about implicitly teaching naming rules. I suggest making a PR where name is changed to your_name (you will have to change it in a few places) and adding a line:

The character `_` in `your_name` is called an *underscore*. Use it to separate words when you want a variable name containing multiple words. You can type it on most keyboards by pressing Shift and hyphen/dash/minus (`-`).

In #23 (comment) I have suggested starting to solve some of the sub-problems in #3. I think it's good for a bit of it to be familiar, while also introducing enough new problems to give a sense of satisfaction of completing something big and teaching them to break down big problems into smaller problems.