The Blog

PDD


« Your Shot

Marzipan Rebroadcast »

Although I never wrote a book about it, I've been talking about my programming methodology, Hate Driven Development, for nearly a decade.

The idea was simple, identify code that you hate, and try to fix it.

It changes so much in your outlook.

Today I want to talk a bit about Pedagogy Driven Development.

Imagine there is some coding concept you want to teach.

Got it?

You come up with an example you are going to use to teach this concept.

Don't fall in love with your example.

So often I see courses or books where the author is letting the example drive what gets done next instead of what needs to be taught.

I catch myself doing this - it's easy to get sucked into it.

For example, let's look at the code that Apple begins with in "Lights, Camera, Code". This is their new content for Swift Playgrounds.

I love Xcode playgrounds. I teach on them many times a month. They've gotten better each year and when a student asks me a question I can often turn back to them and have them try out their idea.

Playgrounds are fun, immediate, and now incremental.

I am more successful with Xcode playgrounds than Swift playgrounds but the platform has such potential.

In the first section of Apple's example, we build a camera.

Here's how I might do it. We're creating an instance of what Apple calls a SwiftyCamera. We could do it like this.

SwiftyCamera()

Just the act of creating the camera is enough to show it and enable it.

If you prefer, we could be explicit about showing the camera. Maybe like this.

show(SwiftyCamera())

Or we could assign our new camera to a variable and send it a message.

let camera = SwiftyCamera() camera.show

We could assume that there is some global notion of a canvas or a world or a space that is the entire viewable area and we could create and show our camera like this.

let camera = SwiftyCamera() space.add(camera)

Remember that everyone at Apple presents Swift as a great learning language. We are teaching students to code. Any of the snippets above is pretty readable and understandable. You get what is going on and when you run the code you see a working camera.

Here's how "Lights, Camera, Code" did it. They gave you the first line below and you added the next three lines in one at a time. You didn't get a working camera until after the last line was entered.

let space = Space() let camera = SwiftyCamera(style: .plain) space.add(camera, at: Point(x: 0, y: 0), size: Size(width: 500, height: 500) camera.start()

The first line creates the Space instance.

Why?

There must be code that sets that Space instance to be the playground's current view. That code is hidden. Why don't we - for now - hide the creation of the Space?

By the way, I have simplified the code that the sample includes. There are three comment lines. The comment lines make sense after we have added the code but in a structured tutorial they do little for the student but show them that there are many more steps.

There's a second "why".

If you run the code at this point the right side of the playground is black. If you comment out the line creating a space the right side of the playground is black. In other words, this code that doesn't make much sense has no pedagogical purpose.

OK.

The second line of code is the first line that the student enters.

let camera = SwiftyCamera(style: .plain)

This line of code includes an assignment statement, a variable, an init, a parameter for that init, and an enum.

No explanation or justification is given for any of this.

This completely ignores that Swift is a great teaching language.

We can play with different styles later. Why doesn't a SwiftyCamera have a default for the style parameter of .plain? That way the student can type

let camera = SwiftyCamera()

The accompanying prose could explain that we create a new camera using the initializer SwiftyCamera() and assign it to the variable named camera so that we can configure and adjust our camera later by sending messages to the object with the name camera.

Run the code.

Still nothing happens.

We should be told ahead of time that nothing will happen. We should be told we are creating a camera but we won't be able to see it until we add it to our scene.

I don't know why we have to add it to our scene in this first example.

Perhaps we're preparing them for the real world where we need to add buttons to their superviews, or add tab bar items to the tab bar view controller.

In a tutorial, I want a quick win. Create a camera and there it is. I don't want an OpenGL style tutorial where I have to create the camera, the lighting, the world, the object, and configure them properly before I see my tea cup.

OK

Say that we do find it pedagogically important to have the student add the camera to the space. We have our space we have our camera, surely we can write code like this.

space.add(camera)

Nope.

Again, we ignore the fact that Swift allows sensible defaults that would allow us to size and position the camera and the student enters the following.

space.add(camera, at: Point(x: 0, y: 0), size: Size(width: 500, height: 500))

But, you argue, the add method belongs to space. Adding defaults for the position and size for any object being added doesn't make sense.

Sure. I understand. We can cover that later. Get the camera on the screen.

It's why I wouldn't even have a space instance visible in this code. The camera would know it's default size and position and if we have to move it we could say

camera.size = Size(width: 500, height: 500)

In that context, a student will completely understand that we are setting the size using a Size instance that has a height and a width.

Contrast that with what this sample has them type instead:

space.add(camera, at: Point(x: 0, y: 0), size: Size(width: 500, height: 500))

I find this code confusing.

We are creating instances of Point and Size inside of our add() method. This is the first method we've seen and it has multiple parameters. The first parameter doesn't have a label and the second and third do. In addition, the formatting of the method makes it difficult for someone new to coding to parse.

Run the code.

Now we see a camera with a view screen and two buttons.

The view screen is blank and the buttons don't respond.

We need to add the code

camera.start()

Why?

This isn't a URLSession where we have to tell it to resume to begin it (which I forget every time).

This isn't a parser which we have to tell to parse once we've finished configuring it.

This is a camera in a demo app which will only contain a camera.

Why would we want to add a camera to this demo that isn't already started?

I can (maybe) understand the argument you'd make in an actual app, but if you want to teach sending messages, how about this:

camera.zoomIn()

or

camera.style = .shark

Here's the thing.

Apple has given us this wonderful tool that allows us to play with our code and see immediate results.

They've given us a fantastic language that makes teaching to code simple.

I want to see demos that take advantage of these strengths.

Blog Index and Subscription Information