Imagine you agreed to write a project for Hyperskill. What is going on next?
Level 0. Before you start
On Hyperskill, projects are complex problems that help users apply the skills they have learned. Each project represents a problem close to a real-life situation: our learners create mini-games, databases, and other interesting applications. Projects are different from topics in that they are much more action-oriented and realistic. While topics have a lot of theory and focus on separate blocks of knowledge, projects require applying the learned material in bulk.
We believe that programming lessons are only effective when they let students face complex coding problems on their own. The learner — even a beginner — gets to write the whole code from the first line to the last starting with just a description of how the program should work. This description does not provide thorough instruction on how to write such a program: the learner has to rely on the covered topics and their own ingenuity.
This process introduces our students to the real-life programmer's workflow: customers do not care how the program works on the inside, but they want it to do exactly what was specified. At the same time, the programmer should always be ready to modify the code because customers often want to add extra functionality. Simple and medium level projects might not illustrate it well, but it becomes apparent with harder projects.
Creating a good project is a difficult task, but there’s no reason to worry: you will be guided by our project managers who will help you throughout the process. To make the project follow the general style of Hyperskill, we will suggest some corrections. This is a natural part of project creation, so don’t be frustrated about such remarks. We will try our best to fit your idea into the general style with as few changes as possible.
Project creation includes many steps: coming up with an idea, the stages, the prerequisites, the tests. Besides, you and our managers will discuss the project at each step of its creation. Keeping all this in mind, don't expect to create a project in a couple of nights: it takes at least a week or two of your part-time work.
There are good reasons to take on this challenging process, though! By working with us, you will take part in teaching programming in an entertaining and fascinating way, thus making practical programming skills more accessible. That’s a great goal to work for, and it will surely be appreciated further in your career. Moreover, you will learn and perfect many skills in the process: smart planning, deciding what language features to use, writing good tests, and much more.
Level 1. Idea
The first and the most important part: choose an idea, i.e. the final product, which is a program. A good final product is:
- Complex. It comprises several technologies, data types, functions, maybe even algorithms and external libraries.
- Educational. It shows the student how to combine all the previous knowledge or even introduces some new technologies or principles.
- Self-sufficient. It can be used as a separate software that performs specific tasks.
- Useful or Interesting. It is a tool that either comes in handy or is just impressive.
Bad Ideas:
“Write a QuickSort” — this is only one algorithm!
“Write a program that counts all the files in a folder” — The result will include a few methods and technologies => “Write a file manager that deletes, adds, copies and renames files”!
“Write a program that hides a number from you and you need to guess it” — the program will be too short and simple.
Vague Examples of Good Ideas:
- Game. At least you can play it in the end!
- Automation tool. Let’s delegate tedious tasks to robots.
- Clone of the famous software or service. Create your own Facebook/Instagram/Spotify.
When you are ready with your idea, write a short abstract in English. Separate it into two short sections:
About. Here you can tell us what’s so unique about your project and why somebody should choose to write this type of program.
Result. In this section, you briefly describe what one can learn while completing the project.
Example:
Project: SMART CALCULATOR
About: Calculators are a great help: everyone is familiar with them. Why not write one yourself, and make it really special? In this project, you will write a calculator that not only adds, subtracts, multiplies, but also is smart enough to remember your previous calculations.
Result: Apart from writing quite a useful program (everyone uses calculators!), you will learn a lot about arrays, stacks, strings, and queues. You will also get a closer experience with BigInteger class.
Checkpoint here! Show the Hyperskill team what you’ve got. If everything's okay, you can go to the next level. If not, try to reread the previous text carefully and follow the recommendations of a team.
Level 2. Plan
Projects on Hyperskill can be compared to Pokemons: they are evolving from something cute and simple to something impressive. The steps of this evolution are called stages.
At this moment, you need to divide your project into these stages. To complete each stage, the student will read some theoretical topics, then develop a stage, and repeat this process until the end. Usually, a project has 4-7 stages.
Pay attention to these stage properties:
- Each stage is a mini-project itself, so it is complex, educational, self-sufficient, and useful! If the program at the end of the stage is not compiling or makes no sense, it is not a stage. Think of a Pokemon: you cannot create a wing and call it alive!
- The difficulty of each new stage is increasing gradually. What does it mean? You cannot ask your student to write “Hello Project” at the end of the first stage, and then go on to create a whole chatbot in the second stage. Evolution is a smooth process, you know. If the project itself looks advanced, you can mark it as designed for intermediate-level users and start with something complicated.
If you think your stages of the project are “evolutional” enough, make a short plan of the stages! Give each stage a name and try to explain what the program will be able to do at the end of each stage.
Let’s continue. Every stage should have a list of prerequisites! For a beginner, nothing in programming is self-evident, nothing is the matter of common sense. Take a look at the Knowledge map and match the topics with the stages. If one topic has a prerequisite, and this prerequisite is also needed for the stage, you should mention only the former. If your project idea needs some extra information (e.g. the knowledge of ANSI encoding), bear it in mind. You will need to explain this part in the description of the stage later.
Now your task is to take the abstract you have already written and add a plan with prerequisites. Mention only those topics that are new for each stage. The result will look like this:
About. Here you have told us what’s so unique about your project and why somebody should choose to write this type of program.
Result. In this section, you have briefly described what one can learn while completing the project.
Stage 1. Name of the stage + the list of prerequisites + the final program at the end of the stage
Stage 2. Name of the stage + the list of added prerequisites + the final program at the end of the stage
…
Stage N. Name of the stage + the list of added prerequisites + the final program at the end of the stage
You can consider the plan of the project “File type analyzer” as an example. The project itself is already on Hyperskill!
Checkpoint again! Show the Hyperskill team what you’ve got. If everything's okay, you can go to the next level. If not, try to read the previous text carefully again and follow the recommendations of the team.
Level 3. Stage Description
The most interesting part starts right here! Now you are going to create a description for every stage.
The main goal of the stage is to make the student think how they can use the prerequisites to develop the code. A description provides extra information that will be needed to implement the stage and thoroughly describes how the final product of the stage should behave. You tell the student how the stage will look from the outside, not from the inside.
Here is an example of a stage description that is clear and structured: take a look! https://stepik.org/lesson/298675/step/1
The description of the stages is a lesson created on the Stepik platform. Each stage represents a separate text step in that same lesson. Here you can find information on how to do it.
We recommend to stick to the following structure:
- (Optional) Theory: Give all the additional information that wasn’t in the prerequisites
- Description: Give a short introduction to why this stage needs to be done
- Objectives: State the main idea and explain the properties of the final program.
- Examples: Show some instances of input/output
How to write a proper text? Imagine that you have a 14-year-old friend who read all the prerequisites. Now that friend is asking about the thing you are going to write. Write the description bearing in mind that this friend will probably read it too. Use Grammarly to correct mistakes!
Try to avoid the following:
- Plagiarism and self-plagiarism
- Documentation-like style
- Indication to specific data types, functions, methods, constructors, or algorithms
- Code snippets (!)
- Advanced concepts that can be omitted
- Links to complicated text sources (Wikipedia is usually one of them)
On the other hand, these things are highly recommended:
- Links to video-tutorials
- Pictures
- Links to interesting resources to those students who want to learn more about the domain of the project
Make sure to reread each description afterward. Sometimes it is a good way to see all the typos are vague explanations.
Read the Number Base Converter project description, it’s another interesting example! The project itself is already on Hyperskill.
Checkpoint again! Show the Hyperskill team what you’ve got. If everything's okay, you can go to the next level.
Level 4. Tests
The project description is done, and so are the stages. Now it’s time to make the process complete and write some automatic tests. Let’s now discuss the technical features, and then continue with ideas & recommendations.
To put it simply, there are two core rules:
- A correct solution should pass the tests!
- An incorrect solution should not pass the tests!
Many things are already covered in our testing library. We advise you to read the documentation carefully. In brief, you will need to create your own class that inherits the parent class from the library and then write two methods that behave as follows:
- First one generates the input data and puts it on the list. 1 list element = 1 test case.
- Second one compares the expected result with a one from the student. If the results don’t match, the method returns a message with a hint. We will discuss these hints a little bit later.
Which type of input data can we use?
- Standard Input
- Some files and their content
- Command line arguments
Which results do we check?
- Standard Output
- The content of a file that was created by a program
There is one important rule: no overengineering! We are sure that you can write an elaborate code, but the tests are not the best place to brag about it. Keep it simple. Maybe in 4 months we will decide to remove one or two test cases, and we will be able to do that if the code is primitive. Feel free to put everything in one file and copy the code blocks! We also recommend to group the tests and sign them in a comment section.
One more thing you need to do is write the correct solution for all the stages yourself. It is important to test the written tests on some solution. Solutions for all the stages should pass the tests.
You are probably wondering how you can test a code properly if you were asked NOT to specify the functions, methods, and classes that the student is ought to use. First of all, on Hyperskill we are always doing black-box testing. It means that we are not checking the functions and methods inside the code, we are just sending something to the code and then evaluating the result of its behavior. The second important thing: you test only those features that you asked to add at the stage description! Remember, nothing is obvious to a beginner.
Don’t worry if you are not a professional tester! Just stay creative and try to think of two things: 1) what are the probable mistakes that the user can make; 2) how the user may try to cheat and send the solution that just seems to be correct. And then start writing!
Take into account a variety of possible implementations for each of your stages. It leads to several important thoughts:
- If your own solution passes all the tests you have created, it doesn’t mean that the tests are correct. Think how else the code could be written. Those interpretations also should be considered as correct.
- Don’t go hard on our students. If one of your stages asks to print the numbers in a row, and a student prints them one per line, is it such a sin? I guess it’s not. The crucial part is the correct numbers! We advise you to check the key components of the stage, not every small detail.
Let’s discuss the situation when the code fails to pass the testing.
First of all, the user will see one of the messages provided by the testing library:
- Wrong answer (we expected another result => we show a tip),
- Exception ( => we show the text of the exception),
- Error (=> we show the text of the error),
- Fatal Error (when the problem occurs in the tests themselves => we ask to pass this information to the Hyperskill team)
Many things are covered by the library, but the “tip” part you can and should customize. Try to give a vague explanation of the problem. For example: “We expected to get a number as an output, but we didn’t” or “Here we were checking the number of created files”.
Here is an example of test cases written in Java:
import org.hyperskill.hstest.stage.StageTest;
import org.hyperskill.hstest.testcase.CheckResult;
import org.hyperskill.hstest.testcase.TestCase;
import java.util.ArrayList;
import java.util.List;
public class EvalTest extends StageTest<Integer> {
public EvalTest() {
super(RealAppEval.class);
}
@Override
public List<TestCase<Integer>> generate() {
List<TestCase<Integer>> tests = new ArrayList<>();
tests.add(new TestCase<Integer>().setInput("2 + 3").setAttach(5));
tests.add(new TestCase<Integer>().setInput("5 * 8").setAttach(40));
tests.add(new TestCase<Integer>().setInput("5 + 5 * 6").setAttach(35));
return tests;
}
@Override
public CheckResult check(String reply, Integer attach) {
int result;
try {
result = Integer.parseInt(reply.trim());
} catch (NumberFormatException ex) {
return CheckResult.wrong(
"Output should contain a single integer number!");
}
if (result != attach) {
return CheckResult.wrong(
"Correct answer is " + attach +
", but your program output " + result);
}
return CheckResult.correct();
}
}