Skip to content

Commit ba3eba3

Browse files
ErikSchierboomee7iHiD
authored
Add syllabus docs (#369)
Draft introduction to syllabus design. I'm trying to give enough background for people to be able to think about syllabus design in a way that is useful and not too overwhelming. Co-authored-by: Erik Schierboom <[email protected]> Co-authored-by: ee7 <[email protected]> Co-authored-by: Jeremy Walker <[email protected]>
1 parent 149ec42 commit ba3eba3

File tree

7 files changed

+291
-0
lines changed

7 files changed

+291
-0
lines changed

building/config.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,34 @@
485485
"title": "Concept Exercises",
486486
"blurb": ""
487487
},
488+
{
489+
"uuid": "038e26ee-891f-4592-92bd-c54cbd58d8bd",
490+
"slug": "tracks/syllabus",
491+
"path": "building/tracks/syllabus/README.md",
492+
"title": "Syllabus",
493+
"blurb": ""
494+
},
495+
{
496+
"uuid": "af70ff3e-d4a4-4968-bcfe-1f197dc43380",
497+
"slug": "tracks/syllabus/first-exercise",
498+
"path": "building/tracks/syllabus/first-exercise.md",
499+
"title": "First Exercise",
500+
"blurb": ""
501+
},
502+
{
503+
"uuid": "6f8d7376-70db-4f25-928c-4778bdf8a686",
504+
"slug": "tracks/syllabus/next-exercises",
505+
"path": "building/tracks/syllabus/next-exercises.md",
506+
"title": "Next Exercises",
507+
"blurb": ""
508+
},
509+
{
510+
"uuid": "cb430e09-7710-43b8-ab0e-2f0ee3785cf9",
511+
"slug": "tracks/syllabus/expanding",
512+
"path": "building/tracks/syllabus/expanding.md",
513+
"title": "Expanding",
514+
"blurb": ""
515+
},
488516
{
489517
"uuid": "ed318b17-01be-4868-92df-50a644adfdc7",
490518
"slug": "tracks/concepts",

building/tracks/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ The track's configuration and metadata are specified in the `config.json` file.
1010

1111
All concept and practices exercises of a track involve _concepts_. These concepts are separate entities by themselves. Check the [documentation](/docs/building/tracks/concepts) for more information.
1212

13+
The concepts taught in the track's concept exercises form a _syllabus_.
14+
For more information on how to design a syllabus, check the [syllabus documentation](/docs/building/tracks/syllabus).
15+
1316
## Exercises
1417

1518
Tracks have two types of exercises:

building/tracks/concept-exercises.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Concept Exercises
22

33
[Concept Exercises](/docs/building/product/concept-exercises) are exercises designed to teach specific (programming) concepts.
4+
The concepts taught by the concept exercises form a _syllabus_.
5+
For more information on how to design a syllabus, check the [syllabus documentation](/docs/building/tracks/syllabus).
46

57
## Metadata
68

building/tracks/syllabus/README.md

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# Syllabus
2+
3+
A fully featured Exercism track has two types of exercises: Concept Exercises and Practice Exercises.
4+
They are fundamentally different and complement each other well.
5+
6+
A track's [Concept Exercises](/docs/building/tracks/concept-exercises) are exercises designed to teach individual concepts that form the basis of a specific programming language.
7+
These concepts form a _syllabus_.
8+
9+
This documentation contains pointers and tips on how to successfully design a syllabus for your track.
10+
11+
## The goal of a syllabus
12+
13+
The end goal of a syllabus is to lead students to be comfortable reading and writing idiomatic code in the target language.
14+
15+
Each individual Concept Exercise is very tightly focused.
16+
It is a small and highly-targeted step that moves the student towards understanding something about the language.
17+
It builds only on concepts that have been introduced previously.
18+
19+
By solving the exercise, the student begins the process of becoming familiar with the concept.
20+
Understanding comes primarily through doing, much less so through explanations.
21+
The explanatory content is there to **introduce** the student to the ideas they need to solve the exercise (thus the choice of filename- "introduction.md")
22+
23+
We want to allow students to start writing code immediately, without having to understand everything up front.
24+
In order to achieve this we hand-wave over details and we leave a lot of things unexplained.
25+
We simplify and provide code stubs where possible.
26+
This reduces the cognitive burden of getting started and provides the time and space for the knowledge to sink in.
27+
By taking this approach we're not saying that the student doesn't need to know these things, we're saying that they don't need to know them **yet**.
28+
29+
Often the earliest exercises need to contain non-idiomatic code.
30+
This is because in the beginning most of the language is still unknown to the student, and most of the concepts have not yet been introduced.
31+
By allowing non-idiomatic code in the earliest exercises, students are able to take many smaller steps in familiar territory rather than a few big steps in unfamiliar territory.
32+
The result is that they are able to reach the stage of idiomatic code more quickly and with less friction.
33+
34+
## Basic structure
35+
36+
Exercises are structured as a tree with an introductory exercise at the top as the starting point.
37+
Later exercises teach concepts that depend on having understood concepts that are taught earlier.
38+
39+
## Porting and borrowing
40+
41+
It can be worth looking at how other language tracks have built out their concept exercises.
42+
You can find examples of Concept Exercises from other language tracks [here](https://exercism.org/docs/building/tracks/stories).
43+
44+
That said, if you decide to use other exercises as a starting point for your own, be careful to ensure that the resulting exercise is about the concept as it exists in your language.
45+
Sometimes concepts differ subtly, sometimes radically.
46+
Sometimes concepts don't exist in other languages at all.
47+
48+
The syllabus, and therefore the concept tree, should represent the concepts that exist in this specific language.
49+
50+
Don't include concepts just because other tracks do.
51+
52+
In some cases it might be tempting to put a concept in because people often have to work around it by using concepts that do exist.
53+
Rather than doing this, introduce the concept that the language _does_ use, and consider adding an exercise that explains how to use it in that type of situation.
54+
55+
For example, in Go there are no enums.
56+
Instead the Go concept tree introduces constants, and teaches how to use constants in the type of situation where you might use enums in other languages.
57+
58+
## Asking for help
59+
60+
Don't hesitate to ask for help.
61+
It's better to ask up front or while working on an exercise rather than discussing during code review.
62+
63+
On GitHub you can mention the team @exercism/learning-mode.
64+
In Slack you can ask in the #learning-mode channel.
65+
Please email [email protected] if you need an invitation to our Slack workspace.
66+
67+
## Getting started
68+
69+
Our experience has taught us that the most pragmatic way to develop a syllabus is to grow the concept tree organically, starting with the simplest concepts.
70+
We don't have to design everything up front, and it's actually generally useful to not think too far ahead.
71+
72+
We start with the bare minimum of concepts — those that are most fundamental to writing **anything** in the language.
73+
We also try to start with concepts that are most familiar to the average developer.
74+
Familiar is good.
75+
Familiar is not confusing.
76+
77+
Remember, while the endpoint is to write idiomatic code, the stepping stones to get there are not always idiomatic.
78+
Using what is familiar — even if it is not a great example of code in that language — helps move a student more quickly toward the goal of code that is more typical of the language.
79+
80+
### Developing the first exercise
81+
82+
Rather than trying to map out the entire concept tree up front, just start with the first exercise.
83+
The goal of the first exercise is to allow the student to start learning with the least amount of friction as possible.
84+
They are taking the very first step towards getting familiar with what code in this language looks like.
85+
They might write a small piece of code, or perhaps just make a couple of additions to a stub in order to complete the exercise.
86+
The students have already solved "Hello, World!" in order to access this exercise.
87+
But in "Hello, World!" they are only changing the wording.
88+
All of the syntax of the language might still be unfamiliar.
89+
Try to optimize for a quick win and getting students familiar enough with the bare necessities of syntax to be able to move forward confidently.
90+
91+
Read more about [developing the first exercise](/docs/building/tracks/syllabus/first-exercise.md).
92+
93+
### The next exercises
94+
95+
The first exercise should unlock a handful of exercises that introduce fundamental concepts.
96+
These will be things like primitives or basic types and simple operations on those types.
97+
98+
Read more about [developing the next exercises](/docs/building/tracks/syllabus/next-exercises.md).
99+
100+
### And then what?
101+
102+
This is where it often starts getting interesting.
103+
There is so much you _could_ introduce at this point.
104+
How do you decide what concepts to tackle next?
105+
106+
It kind of doesn't matter.
107+
As long as you start somewhere that seems reasonable, it will be fine.
108+
109+
Read more about what we think "reasonable" means in the context of [expanding the concept tree](/docs/building/tracks/syllabus/expanding.md).
110+
111+
## Do not convert practice exercises
112+
113+
A good Concept Exercise is extremely focused, and ideally teaches only one concept.
114+
There will usually be only one expected approach to solving it.
115+
This is in contrast to Practice Exercises, which are open ended and lend themselves to exploration.
116+
117+
A good Concept Exercise is usually a bad Practice Exercise, and vice versa.
118+
Since the goals of Practice Exercises and Concept Exercises are completely different, we do not take Practice Exercises and convert them into Concept Exercises.
119+
We write all Concept Exercises from scratch or base them on stories that were explicitly crafted for the purpose of teaching simple concepts.
120+
121+
## We encourage hand-waving
122+
123+
Sometimes you'll feel like there is a deadlock.
124+
Concept A requires understanding concept B, and B requires understanding A.
125+
126+
In this case simplify.
127+
Hand-wave over some complexity in one so that you can get students familiar with the other.
128+
It's perfectly fine to say that something will be introduced in more depth later, and that for now the student just needs to understand this one bit.
129+
130+
Concepts are understood more deeply in stages and over time.
131+
132+
## Selecting stories
133+
134+
A concept exercise always has a story.
135+
136+
If you're forking an exercise from another track, then the exercise will already have a story.
137+
In that case, you're all set.
138+
139+
To see if there are any existing stories you can use or exercises you can fork, check out the [list of stories](docs/building/tracks/stories).
140+
141+
If you have a concept but no story then our recommendation is to write a small, simple code example that uses the concept that you're introducing.
142+
Then reverse engineer a story onto the code.
143+
Keep the story stupidly simple.
144+
It doesn't have to be good fiction.
145+
It doesn't need a strong plot or character development.
146+
It can be just a couple of lines long.
147+
148+
Bounce ideas for stories with the Exercism team.
149+
We have a lot of experience coming up with suitable stories.
150+
151+
Once you have a story you will likely need to tweak the code a bit to get it to fit the story.
152+
153+
## Contributions from the community
154+
155+
Working on a syllabus involves two separate but intertwined activities:
156+
157+
1. Syllabus design: selecting and ordering concepts
158+
2. Exercise implementation: writing documentation and creating exercises to teach those concepts
159+
160+
We've found that it's both fun and enriching to get the wider community to contribute to implementing exercises.
161+
The syllabus design itself, though, is easier to tackle with a small team of contributors who are all engaged in building up an understanding of the full syllabus with all of its intricacies.
162+
163+
That said, we recommend that the syllabus design team implements the first five or six concepts first, before opening up for community contributions.
164+
This helps ensure that the people on the core team of syllabus designers understand the process themselves before having to review pull requests from people in the broader community.
165+
166+
It's also easier to create issues for these higher-order concepts and tends to be more fun for community members to work on them, since there are fewer constraints to worry about.
167+
168+
## Creating issues
169+
170+
We still haven't figured out how to best create issues for creating concept exercises.
171+
172+
In some tracks we've tried creating separate exercises for the concept itself and the exercise.
173+
In others we've tried making issues that have a checklist to work through.
174+
Overall, we think this is still too intimidating, and we'd like to find a better way.
175+
176+
Please talk to us about the process as you start making issues, and we will do our best to help figure out how to proceed.
177+
178+
We will update the documentation as we learn better ways of tackling this.

building/tracks/syllabus/expanding.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Syllabus - Expanding
2+
3+
Once you've built a few concept exercises it becomes easier to expand the syllabus.
4+
This is because you now have access to more concepts that you can build on.
5+
6+
The two main ways that we expand a concept tree are to:
7+
8+
1. build on an existing concept (e.g. `time` => `timezones`)
9+
2. introduce a new concept that depends on a concept that has already been introduced (e.g. `classes` => `interfaces`)
10+
11+
If you're at a loss for what to choose next, take a look at one or two of the simplest practice exercises that exist for your track.
12+
Identify the concepts that are used, and pick one that hasn't been covered yet in the syllabus.
13+
14+
You might discover that the exercise you're working on requires understanding a concept that hasn't been introduced yet.
15+
Just make a note of it and finish the exercise with the assumption that the student already understands the missing concept.
16+
Remember to set the status of the exercise to `wip`, as having gaps or jumps in the concept tree will be very confusing to students who are unfamiliar with the language.
17+
18+
It's worth taking a look at other tracks to see how they've structured their syllabuses.
19+
For example the [Elixir track](https://exercism.org/tracks/elixir/concepts) has a really nice syllabus progression.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Syllabus - The first exercise
2+
3+
The first exercise should cover the concept `basics`, and it should have no prerequisites.
4+
It should provide only enough information to allow the student to solve the exercise at hand.
5+
6+
Many tracks have already implemented an exercise covering `basics`.
7+
To familiarize with what is commonly taught in such an exercise, we recommend that you go sign up to a few different tracks that have Learning Mode, and solve the first concept exercise.
8+
9+
Each language is different, and you might find that you need to introduce more than other tracks do, or less.
10+
For example, if you need to compile a program to get it to work, this is something that you'll want to mention in the introduction to the exercise.
11+
12+
Other things that are often covered within the `basics` exercise are:
13+
14+
- function or method definitions
15+
- calling functions
16+
- passing arguments to functions
17+
- assigning a value with a name (variables and/or constants)
18+
19+
Use as few data types as possible.
20+
If you can manage, use only integers, as their notation is the same across most languages and will be well known to virtually everyone.
21+
22+
If there's a track for a language that is similar to yours, go ahead and check if you can fork their exercise and use it as a starting point.
23+
24+
Aim to be concise; you don't want to overload students with information.
25+
The introduction should explain _just enough_ that the student can look at the code and identify what the different parts are.
26+
They don't need a deep understanding of any of it, but they should also not be left wondering what something is.
27+
28+
The student should only need to actively _use_ one or two concepts.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Syllabus - Next Exercises
2+
3+
Having implemented your first concept exercise, the next few exercises should build on that.
4+
5+
We like to have three to five exercises that have no prerequisites other than the `basics` concept.
6+
7+
Good options are the core primitives or data types of your language.
8+
E.g. booleans, basic numeric types, strings, and atoms.
9+
10+
It's worth checking other tracks' concept exercises to see if there are any that are appropriate for your track.
11+
12+
Note that introducing a concept doesn't mean that you need to explain it fully in all its glory.
13+
You can always defer complexity.
14+
The language might have a dozen different numeric types that are useful in different scenarios.
15+
The exercise can simply mention that there are others while introducing only the most commonly used integer type and most commonly used floating-point type.
16+
17+
Some core data types are too complex to introduce directly.
18+
For example strings might be lists of chars.
19+
In such a case you would need to defer the introduction of strings, and design a concept exercise for chars and another for lists.
20+
Then you can add an exercise for strings that has both of those exercises as prerequisites.
21+
22+
Sometimes while working on an exercise you will realize that it's more complex than you expected.
23+
That's totally fine.
24+
Make a note of the concept that needs to be taught as a prerequisite.
25+
Then pretend that such an exercise exists, and finish the exercise you're working on with that simplification in mind.
26+
Then go back and create a new exercise for the prerequisite concept.
27+
Remember to mark the exercise as `wip` until the prerequisite exercise has been added.
28+
29+
Another thing that can happen at this point is that you find that you have cyclical dependencies.
30+
You need to introduce two concept, but each concept relies on the other.
31+
In this case you may be able to use a stub.
32+
Then you can explain that the dependent concept exists, but reassure them that they don't need to understand it yet.
33+
Another option would be to give a bare minimum of an introduction, enough for the student to get past the hurdle, while reassuring that the concept will be covered in more depth later.

0 commit comments

Comments
 (0)