• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Junilu Lacar
  • Jeanne Boyarsky
  • Bear Bibeault
Sheriffs:
  • Knute Snortum
  • Tim Cooke
  • Devaka Cooray
Saloon Keepers:
  • Ron McLeod
  • Stephan van Hulst
  • Tim Moores
  • Tim Holloway
  • Carey Brown
Bartenders:
  • Piet Souris
  • Frits Walraven
  • Ganesh Patekar

Programming club

 
Ranch Foreman
Posts: 266
12
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello Ranchers,
I am doing a community project to teach programming. The club is for mums and their daughters, or any girl and woman, at beginner lebel.
I found Junilu's refactoring of my code quite inspiring, and realised I might teach fundamental concepts really wrongly!
So I wondered if some of you could share programmimg exercices that are at the same time really fun, engaging and done the right way, to ensure my pupils get solid basis?
We are at hello world and string concaténation right now so there is no urgency with TDD.
 
Marshal
Posts: 14053
234
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm glad that I could provide some inspiration for you Here's a crazy idea (see my new tagline in my sig below): I have a theory that teaching future programmers by showing them how to use tests to their advantage right from the start can actually help them learn how to program better and faster.

I was listening to an old podcast where Kent Beck was interviewed and he said the following:

(on the importance of TDD) I would imagine some functionality and my next thought was “How am I going to test that?” … If you can’t write a test for it, then you have no business programming it.

When I’m writing tests, I’m not just writing tests. I’m making API decisions, I’m making analysis decisions and the tests just happen to be the notation that I use to record those decisions.


For me, a test written before the production code isn't really a test at that point. It's a plan for what you're going to write. As Kent Beck says, it just so happens the notation used to record that plan is in the form of tests.

One of the most important skills we should be teaching aspiring future programmers is how to plan, experiment, learn, and replan. This is basically the scientific method applied in the context of problem solving through computer programming.

I would love to contribute to your effort. There are a few fun exercises I use in the workshops I give in my work as a consultant. One is Tic Tac Toe.  Another is the Conway's Game of Life.
 
Rancher
Posts: 1180
16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

D.J. Quavern wrote:Hello Ranchers,
I am doing a community project to teach programming. The club is for mums and their daughters, or any girl and woman, at beginner lebel.
I found Junilu's refactoring of my code quite inspiring, and realised I might teach fundamental concepts really wrongly!
So I wondered if some of you could share programmimg exercices that are at the same time really fun, engaging and done the right way, to ensure my pupils get solid basis?
We are at hello world and string concaténation right now so there is no urgency with TDD.



First off... my hat's off to you for taking on this project.

TDD or other development process isn't really an advanced concept to be taught only once people have reached some high level.  Rather, it's a foundation for how to do the nuts and bolts of software development.  Of course, writing tests requires you to be able to write real code with some level of expertise.  That's fine - just make the test code part of what you need to program.  For instance, if the first project is a Fibonacci number generator, don't teach just how to generate the numbers.  Instead, show how to do the whole TDD process to write a well-tested program to generate Fibonacci numbers.  ...if TDD is indeed the process you want to use.

Similarly, such ideas as using variable names that are recognizable from the problem domain (such as "rank" and "file" or at the very least "row" and "column" instead of "i" and "j") or keeping methods down to a reasonable size should be taught and indeed emphasized from the beginning - not retrofitted in later.

That's my take on it.  Any other thoughts?

EDIT: That's what I get for taking so long to reply - someone else gets in there first.    At least some of our thoughts overlap.  
 
D.J. Quavern
Ranch Foreman
Posts: 266
12
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow two cows! And a piece! Thank you, you should not have *chewing of pie intensifies*

Yes, absolutely for TDD when the time comes. It's way to early now. I almost lost all the audience when I explained variable in an intricated way. We need to learn how to write to be able to write TDD.

Yes to tic-tac-toe: what is the minimal datastructures to know to make a tic-tac-toe? In other words, do we need arrays?

Yes to planning/replaning: I will start this week when we will speaker about conditional branching.

Yes to explicit variable names, this is something I already missed!

Yes to short methods limited to what they are doing, when we reach this point.

The program we have done up to now are printing and reading inputs, to create à dialogue with the user.

Any other ideas? As a consultant or during any other professional/hobby activities, do you had this precious moment where you saw your participants get this "aha!"-feeling, or something they really enjoyed?
It's a sunday activity so if people don't think it's fun, they will stop coming I am afraid.

 
Junilu Lacar
Marshal
Posts: 14053
234
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

D.J. Quavern wrote:Yes, absolutely for TDD when the time comes. It's way to early now. I almost lost all the audience when I explained variable in an intricated way. We need to learn how to write to be able to write TDD.


I think you're right. TDD is about telling stories. To tell a story, you need to start with being able to build up a vocabulary of words first, then be able to form phrases, then sentences, then paragraphs.

Yes to tic-tac-toe: what is the minimal datastructures to know to make a tic-tac-toe? In other words, do we need arrays?


Ah, now you've gone and taken it too far. Writing Tic Tac Toe is telling a story now. When you get to the point where you're ready to write Tic Tac Toe, you need to think about the characters, the plot, and the arc of the story. Thinking about data structures and arrays is thinking about how many chapters and what kind of punctuation you're going to use. That's absolutely not the level of abstraction you need to be thinking in.

Do you see what I mean?

For now, I would suggest you keep challenges small and appropriate to the level of abstraction you're trying to teach.

1. How do I make the computer display a message? Teach them how to use System.out.println(). Write a program that displays the message "Hello, world!" (Traditionally, every programmer's first program)

2. How do I tell the computer something? Teach them about the Scanner object and variables. Enhance the first program to make it ask for the person's name, then put that name in a variable, then make the computer display the message "Hello, <name>, it's a pleasure to meet you!"

3. How do I make the computer decide between two choices of things to do? Teach them about boolean expressions (true/false) and how an if-statement works. Extend the program even more and make the computer ask whether it's past 12 noon. "Is it past 12 noon yet?" If the answer is "Y" then display "Good afternoon, <name>!" otherwise display "Good morning, <name>!"

Keep extending this program as you introduce more types of program statements: for loops, while loops, then introduce methods, etc.

This is how I would keep them engaged. Then challenge them to come up with their own little scenarios where they might be able to use the programming "words" they have learned to create "sentences" then "paragraphs".
 
Junilu Lacar
Marshal
Posts: 14053
234
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's another idea when you are ready to introduce them to objects.

Think of objects as a way to make it easier to perform complex operations by giving them simpler interfaces. Think of a car, for example. The interface to a car includes a steering wheel, a gas pedal, and brakes. These are relatively simple mechanisms to understand and help you control the car and make it do things like go forward, stop, and turn. These operations are representations of the driver's intent, right? The mechanisms they are attached to, the linkages, the gears, the engine, all that are hidden under the hood. These are the implementation details.

Likewise for objects. System.out is an object. The println method is an interface to that object that you use to carry out an intent, which is to write something on the display device. What happens under the hood of the System.out object when you call the println method is relatively complicated if you dig down into its implementation details. Normally, you don't care about those details because you just want your intent to be carried out.

The things you pass to the println method are your inputs. These are analogous to how much you press down on the gas, or how hard you step on the brake, or how much you turn the steering wheel.

Combining all that, a call to System.out.println() is how you tell the computer to do something using an object (System.out) to carry out a specific intent (println). It's how you say in Java something like "Hey, System.out object, please print 'Hello,' then my name, then a '.' on one line in the display."

Then give them exercises like: Imagine we wanted to control a light. What kind of object would we create to do that? What would be our interface to that object to hide the complex implementation details of carrying out our intent?

A possible solution:

Now, given that interface (don't even think about what would go between those braces yet, where the ...s are) ask them to come up with the commands they would write to
1. Create a new light
2. Turn that light on
3. Turn that light off
4. Flip it to its opposite state. That is, if it's on, turn it off, or if it's off, turn it on.

Challenge them to use those commands and other things they've learned so far to tell a small story, like this: write a small program using the light object that simulates a random number of people who line up and, one after another, flip a light switch to its opposite state. Display the state of the light after the last person has flipped it.

Then challenge them to come up with their own examples of objects and how they might define an interface to interact with those objects. Ask them to tell a story with those objects.

I think this would be a good one-hour exercise to get them thinking in terms of objects properly.
 
Marshal
Posts: 65814
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:. . . The mechanisms . . . linkages, the gears, the engine, all that are hidden under the hood. These are the implementation details. . . .

. . . and those implementation details are different in different cars. You don't need to know whether you have a petrol engine or diesel or electric to be able to pull away.
 
D.J. Quavern
Ranch Foreman
Posts: 266
12
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you guys!
It's great ideas and good principles.

At the risk of disappointing you greatly, we have this club in Python.

The first program we wrote was a program printing "hello", taking their names as input and replying.

Next program we work with as a repetition is a program asking for their names and repeating it, asking for their favorite color and saying it's also their favorite color. And then asking their favorite animal and commenting on it. You get the idea.

The week after, I thought about implementing if statements in a password program. The program will ask for an input, and if the input equals the variable password, print that they have the right password.

I had no idea that System.out was an object!

I like the idea of the light. I think I will implement it with Python's library tinker. To have an actual light going on and of!
 
Junilu Lacar
Marshal
Posts: 14053
234
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

D.J. Quavern wrote:we have this club in Python.


Well then V. Anton Spraul's Think Like a Programmer, Python Edition will be perfect for you!
 
D.J. Quavern
Ranch Foreman
Posts: 266
12
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:

D.J. Quavern wrote:we have this club in Python.


Well then V. Anton Spraul's Think Like a Programmer, Python Edition will be perfect for you!



Unfortunately it seems that this book had been cancelled  
https://www.reddit.com/r/learnpython/comments/8iy7yi/did_think_like_a_programmer_python_edition_get/

It is unavailable on Amazon.
 
Junilu Lacar
Marshal
Posts: 14053
234
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Too bad. The original book that uses C++ is still useful though, if only for the exercises. I'm sure that with some familiarity of Java, you can translate the C++ code to Python without much trouble. And if you do run into some C++ code you don't quite understand, we have a forum for C++ questions, too.
 
D.J. Quavern
Ranch Foreman
Posts: 266
12
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:Too bad. The original book that uses C++ is still useful though, if only for the exercises. I'm sure that with some familiarity of Java, you can translate the C++ code to Python without much trouble. And if you do run into some C++ code you don't quite understand, we have a forum for C++ questions, too.



I actually have a c++ question but you might be very, very angry at me...
 
Junilu Lacar
Marshal
Posts: 14053
234
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

D.J. Quavern wrote:I actually have a c++ question but you might be very, very angry at me...


C'mon, when have we ever answered in anger here? Many of us have strong opinions which tend to come across forcefully in our responses but for the most part, we like to think we're patient, open-minded, and above all, respectful. In general, never withhold a valid, reasonable question because you think anyone here might get angry at you. Not gonna happen; and if it does, there are plenty of moderators who will make sure to correct the situation.

So, what's your question? (Please post it in the C/C++ forum though)
 
D.J. Quavern
Ranch Foreman
Posts: 266
12
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:

D.J. Quavern wrote:I actually have a c++ question but you might be very, very angry at me...


C'mon, when have we ever answered in anger here? Many of us have strong opinions which tend to come across forcefully in our responses but for the most part, we like to think we're patient, open-minded, and above all, respectful. In general, never withhold a valid, reasonable question because you think anyone here might get angry at you. Not gonna happen; and if it does, there are plenty of moderators who will make sure to correct the situation.

So, what's your question? (Please post it in the C/C++ forum though)



As usual, it involves some ugly code ;).
I think I solved it. (Maybe)
 
Junilu Lacar
Marshal
Posts: 14053
234
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

D.J. Quavern wrote:
As usual, it involves some ugly code ;).
I think I solved it. (Maybe)


Don't be coy. Share the code so others might learn as well.

Ugly code is nothing to be ashamed of. Everyone has written ugly code. I write ugly code all the time. The only difference is that I recognize it and I do something about it. I never attach my ego to ugly code I write. I see it as a way to purge the fog of misunderstanding from my brain and make it crystal clear to the computer, and myself, what it is I actually want to say to the computer.
 
Junilu Lacar
Marshal
Posts: 14053
234
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
By the way, have you had another club meeting yet? If so, how did it go? Did you use any of the ideas discussed here? I'd love to hear about it.
 
D.J. Quavern
Ranch Foreman
Posts: 266
12
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes. We went through cristal clear variable names! It went home for some of them, but not all.
Some did not see the point of changing a variable name or implementing new variables since the value inside a variable could change. So why not recycle they said?
The variable "name" has been used for everything ranking from food to places, and animals....

I am not ashamed of my ugly code when it's for puzzle* problems, as long as it does the job I am usually fine with it.

*edit: I changed competitive for puzzles, as I do it more recreationally.
 
Campbell Ritchie
Marshal
Posts: 65814
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

D.J. Quavern wrote:. . . I am not ashamed of my ugly code when it's for puzzle* problems, . . .

Careful; that tells me you tolerate bad habits when your programming is kept private.
 
D.J. Quavern
Ranch Foreman
Posts: 266
12
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:

D.J. Quavern wrote:. . . I am not ashamed of my ugly code when it's for puzzle* problems, . . .

Careful; that tells me you tolerate bad habits when your programming is kept private.



I do tolerate those bad habits. Party because I have a very short time per problem and since I understand my code, I don't want to invest more time in a verbose solution. (comments were for you guys). No, I did not forget what Junilu and you said about opaque code inviting bugs, I just don't have days to write my solution.

I tolerate lots of bad habits when kept private. Let the one who never loudly farted on one's sofa when alone throw me the first stone 😀😀!
 
Campbell Ritchie
Marshal
Posts: 65814
250
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But flatus dissipates and vanishes if confronted with enough fresh air. Opaque code can come back years later to bite you.
 
Bartender
Posts: 3519
150
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

D.J. Quavern wrote:Let the one who never loudly farted on one's sofa when alone throw me the first stone 😀😀!

Since I qualify, let me know in what direction to throw.

But I am with DJ here about those bad habits. I have done quite some HackerRank puzzles. My first attemps were with nice classes and superb methods, only to find out I was the joke of the town, competing with those 4 lines python solutions. My motto is now: solutions as short as possible, readability is irrelevant.
 
Campbell Ritchie
Marshal
Posts: 65814
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You should go in for those obscured C contests.
 
Marshal
Posts: 7181
492
Mac OS X VI Editor BSD Linux
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Piet Souris wrote:My motto is now: solutions as short as possible, readability is irrelevant.


To some extent that works, especially when the problem is relatively easy to solve, and I've done it million times too, in Advent of Code event for instance.

However, each time I faced some more complicated problem, dirty and ugly way didn't work out well for me - in different words, I got stuck because couldn't cope with complexity of the problem and lost the track what I'm doing. Tackling problem in a disciplined way, writing the tests to verify my assumptions, as well as building code up from small pieces - led me to a successful solution. And that wasn't an accident, because that happened multiple times.

Probably not ironical at all, but I felt more proud of myself when I looked at the solution to which I putted more (much more) heart.


Since those days, I promised to myself that I will practice and will approach problems being in a TDD mindset, well, got to be honest, broke my promise to myself many times since then, but I still keep trying. That is certainly a most challenging thing I've faced in my programmers career so far. Interesting enough, I see the strong purpose of that, and at the same time finding hard to make it built-in approach in my toolset.

For those who never heard of TDD (=Test Driven Development), my personal goal is, not to start on production code until I haven't designed a reasonable, self documented test case. <-- there is more into it
 
D.J. Quavern
Ranch Foreman
Posts: 266
12
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Piet Souris wrote:

D.J. Quavern wrote:Let the one who never loudly farted on one's sofa when alone throw me the first stone 😀😀!

Since I qualify, let me know in what direction to throw.


Follow the noise.

Piet Souris wrote:But I am with DJ here about those bad habits. I have done quite some HackerRank puzzles. My first attemps were with nice classes and superb methods, only to find out I was the joke of the town, competing with those 4 lines python solutions. My motto is now: solutions as short as possible, readability is irrelevant.


Isn't that true!!
And then you spent three days designing a whole video game for something that can be solved in 5 rows code!
 
D.J. Quavern
Ranch Foreman
Posts: 266
12
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Programming club is on Sunday.

1. We are doing if statements. Shall I use a password guessing program, what do you think? Guessing the right password will make a congratulation message appear? Anything fun coming to mind with if-statements?

2. Generally, what do you think about sending code in advance to participants? I thought they might be less intimidated?
 
Campbell Ritchie
Marshal
Posts: 65814
250
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Never mind about intimidation; seeing the code in advance allows your people to understand it and to ask interesting questions. That would be a good idea.
 
D.J. Quavern
Ranch Foreman
Posts: 266
12
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Morning Ranchers!

What do you think of this little piece, as concept?
It would allow us to :
- repeat if/else
- introduce elif
- repeat indentation and syntax
- discover that programing languages have native methods (.lower in this case)
- hopefully have some fun




If anything else comes to your mind...
 
Campbell Ritchie
Marshal
Posts: 65814
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That has all sorts of little errors in which should make for interesting discussions. And some serious conceptual errors, too. Again something you can discuss.
 
D.J. Quavern
Ranch Foreman
Posts: 266
12
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:That has all sorts of little errors in which should make for interesting discussions. And some serious conceptual errors, too. Again something you can discuss.



Break it to me now before I teach that on Sunday!
 
Campbell Ritchie
Marshal
Posts: 65814
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Translate your code into Java®.
  • 1: You have a colon : after else. Translate that into else; in Java® and discuss what can now go wrong. Work out how you would pick up such an error.
  • 2: You have the == operator used on the password. Discuss the difference between object identity and object equality. When I was doing my MSc, one of the other chaps used == and it worked, until he serialised and deserialised all his objects. Why didn't his program work for the deserialised version? He had previously written lots of C#. Why did he therefore think that == would work?
  • 3: Explain why MAMMA is such a good password. 'Show how much you love your mum' isn't really polite in some places.
  • 4: Discuss the problems you can get if you store passwords. Students are taught how to check whether a password is equal to a stored value, but that isn't at all secure.
  •  
    D.J. Quavern
    Ranch Foreman
    Posts: 266
    12
    IntelliJ IDE Firefox Browser Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Campbell Ritchie wrote:Translate your code into Java®.

  • 1: You have a colon : after else. Translate that into else; in Java® and discuss what can now go wrong. Work out how you would pick up such an error.
  • 2: You have the == operator used on the password. Discuss the difference between object identity and object equality. When I was doing my MSc, one of the other chaps used == and it worked, until he serialised and deserialised all his objects. Why didn't his program work for the deserialised version? He had previously written lots of C#. Why did he therefore think that == would work?
  • 3: Explain why MAMMA is such a good password. 'Show how much you love your mum' isn't really polite in some places.
  • 4: Discuss the problems you can get if you store passwords. Students are taught how to check whether a password is equal to a stored value, but that isn't at all secure.


  • Hi again!
    Thanks for your comments, but security is overkill.

    1. Python uses ":" after "if" "elif" and "else", this is the correct syntax.

    2. I know that, but it's their third hour programming. Python only uses pointers to objects so it allows string comparison with ==. I know I need to use compareTo() with Java.

    3. We are not building a banking app, just four lines of code to understand if/else/else if, so that's not the point. The point with the comparison is that they understand that a compiler will not interpret MARSHAL and marshal as the same thing and that capitalization matter. The kids are 8 to 11 years old, they love their mums!

    4. They are small kids doing their third hour programming. Password security is beside the point.

    Anything else?
     
    Campbell Ritchie
    Marshal
    Posts: 65814
    250
    • Likes 2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    D.J. Quavern wrote:. . . . Python only uses pointers to objects so it allows string comparison with ==.

    That allows you to discuss the difference between languages.

    I know I need to use compareTo() with Java.

    No, it is in C that you have to use strcomp(). In Java® you would use equals().

    . . . The kids are 8 to 11 years old . . . They are small kids . . .

    I never knew that; I thought you were all adults. All you have to do is say, “If you store passwords like this, somebody else can easily find them.” That will tell them everything they need to know.

    The reason the chap got his program to work with == was that he was using String literals for everything. If you assign Strings from literals, the == operator will seem to work. When you serialise and deserialise the objects, in Java® you get different objects, so == no longer works. He had worked in C# where == is overloaded for String equality.
     
    For my next feat, I will require a volunteer from the audience! Perhaps this tiny ad?
    Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
    https://coderanch.com/wiki/718759/books/Building-World-Backyard-Paul-Wheaton
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!