That Time I was sent to another world to become a Software Engineer
Prelude
Your eyes continue to wander abstractly around the room, you’re drenched in sweat, your legs cannot stop shaking. In front of you are several middle-aged men, whispering to each other. Occasionally their eyes would take a sharp gaze at you. That is until one of them stood up and called your name.
"I'm sorry, but our company has decided not to go through with you." Spoke one of the men. You didn’t hear anything he said after that. Emptiness fills you, but strangely enough, you feel relieved.
After a few times of going through the same cycle: Arriving full of hope, followed by a long and convoluted process, only to get hurt by a piercing, sugar-coated response, hearing even the slightest bit of painful yet comely sentence as that must be met with joy. "At least they didn’t tell me to wait." You thought. After the gut-wrenching experience, all you want is assurance, and at least you got it today.
You step out of the building with the same mood as before. You peer long into the distance, away from the busy street of the capital city, still with your lonely heart. Even after many long and annoying attempts have steeled your resolve, somewhere inside, you had hoped that today would be different, that your search would finally be over.
As you take another step, rain pours over the crowded street of the night, driving you to run for shelter at the worst possible time.
Until suddenly, the rain stopped. You can see tiny droplets floating in the air. All the cars, the people, the entire city, frozen solid. It’s as if time has stopped. What is happening? Is this a dream? Many questions went through your mind, but there’s simply nothing that could answer them…. At least that’s what you thought.
"It's all real. What do you think? Beautiful, isn’t it?"
A voice echoes from beside you. The myriad of questions written on your face suddenly got their answers. The person smiled in a way that you’ve never seen before. You know that their smile is hollow, yet you don’t feel animosity coming from it. But one thing you’re sure of is that you’ve never seen that kind of smile on a person’s smile before. “Are they even human?” You thought. Even if that’s true, they’re no one ordinary.
“What are you?” Those are the first words that slipped your mouth after seeing their cold expression and ominous presence. If this happened to anyone else, they’ll probably utter the same thing. But they, no, “it”, did not answer you. It merely countered your question with another.
“You’re looking for a job, right?” That thing then stopped right in front of you, pulling out a piece of paper before continuing. “Work for my company, in a different world.” Said the creature with a grin.
The creature went to explain after that. You don’t understand much of what it is saying. A different world, magic, a modern parallel existence to our own. Meanwhile, it kept going on and on, paying no heed to your confusion. Of course, there are lots of things going through your head. Why does it know you’re searching for a job? Why you? Does magic really exist? And many others, yet none can come out. You kept listening. Even if you can’t follow what’s going on, it seems that you can’t help but listen. Are you swayed by its charisma? Or does it have some sort of power to force you to tune into it? Both of your questions go unanswered.
“So, you must be interested, no?”
Either from its powers or you just feel hopeless from the barrage of rejections, you gladly accepted. It welcomed your answer with a satisfied look.
“Ah, that’s right, I haven’t given you my name.” It bowed slightly. “I am R̵͇̗̈̅̇̐̚e̸̪̯͖̠͍͊̂̋͗͝y̷̧̗͚͚͑͒̔̓a̸̩͕̎̏͌l̴̞̔̄͒̍̕l̵̡̬̱̹̇̈́̐͋͜͝e̵̲͆͒.”
You cannot hear its name. As if something had prevented you from knowing it.
“Ah, then call me 0. Not everyone can hear my name. Alright, without further ado, let’s take you into my world.”
And with that, R̵͇̗̈̅̇̐̚e̸̪̯͖̠͍͊̂̋͗͝y̷̧̗͚͚͑͒̔̓a̸̩͕̎̏͌l̴̞̔̄͒̍̕l̵̡̬̱̹̇̈́̐͋͜͝e̵̲͆͒ sent you into another world. You’ve never felt so uncertain before when the journey began. An amount that would never be possible before accepting 0’s contract. With an unsteady footstep forward, you looked back cynically, to yourself, a few minutes in the past. “I’m sorry, our company has decided to not hire you.” Spoke one of the men. The rest of his words feel foreign to you. Emptiness surrounds you, but strangely enough, you feel relieved.
A fun first day? You must be joking
You sat down in a room after one of your superiors showed you around your new workplace. There’s nothing out of place. Even though you know that this world is not yours, fundamentally, it’s the exact same. At least from seeing your work and living quarters.
When you hear the word “Another world”, many things go through your mind. A place where magic, mythical creatures, and other things that defy logic would be in abundance. A modern society where most of its populace are office workers would never be your guess. Yet what you’re witnessing now is the exact opposite. Despite all that, you feel relieved. “I guess I don’t need to change my lifestyle.” You thought.
“Sorry, did you wait long?”
You peered towards the voice. You see your superior standing with a couple of other people. Some of them are smiling, but with a seemingly forced one. Still, you need to recognize their efforts. They wore badges with their names and “Software Engineer” written on it. They must be your co-workers then.
“These are your team members. You’ll be working together with them.” Said your superior. He then gave you a couple sheets of paper before heading back to his room. “They’ll explain your job in this division. Good luck.”
Just like that, he left your vision, leaving you with a somewhat confused expression. Ever since you met him, he has always acted cold. Only speaking when it’s necessary. You wondered if he knows about 0. If so, you have a few things you want to ask him yourself. But 0 forbids you from talking about it or that you came from another world. Even if he didn’t, you doubt your superior will answer anyway.
“Don’t mind him. He’s a man of few words.” Said one of your co-workers, as if you’ve been saying what you’re thinking out loud.
“Ah, no problem.” You retorted with a small laugh to mask your dissatisfaction.
“I’m Rory, Rory Auden. Call me Rory. And over there is Emory, Riley, and Alex.” Rory introduced each member of the team to you. “And now I shall explain what our division does.”
“Our sub-division focuses on the backend. Well, sometimes the frontend guys require extra manpower, so we often need to dabble in that too.” Rory said with an uneasy laugh. You can tell Rory is not thrilled whenever that happens.
“So, because of that,” Rory pauses while going through files on their computer. “As a new member of our division, I would like to ask you to make a full-stack application to keep your edge, just a precaution.” They continued.
First Task
“I’m not going to hold your hands on this one. But I’ll explain some things you may need to know.”
Rory shows you a document, a “requirements” of sort of the application they want you to make. It seems simple enough, but there’s one problem.
“This web framework… Spring Boot?”
“Bingo.” Answered Rory, confirming your suspicions. “I’m asking you to make that application with Spring Boot. Good luck.”
“Wait!” You shouted. Rory only gave you a wave and left you with no idea of what to do. You can only stare at the document with feelings of resignation.
“Do you need some help?” Touted another co-worker coming towards you.
“Ah, yeah, somewhat. I’m not familiar with Spring Boot. You’re Emory, right?”
Emory nodded. “I can guide you. What do you usually work with?”
“Django and Laravel. But I’m more confident in my Django abilities.” You responded.
Emory suddenly pulled you away into their room and locked the door as soon as you mentioned that.
“What are you doing?” You stare at Emory with bewilderment, only to be met with the same expressionless face.
“You’re from another world, aren’t you?”
Emory’s question made you panic. 0 warned you to not tell anyone about it. Even so, on your first day of work, your secret has been exposed.
“Calm down. I came from the same world as yours.” Emory seemed to notice your inner turmoil and tried to calm you down. “Don’t worry, the people of this world won’t know that. I noticed from your way of pronouncing foreign terms in this world’s language. The translation power of “it” is not perfect. I recommend you learn the native tongue.”
You’re stumped after hearing Emory’s explanation. You can only react with a simple nod. You see that other people can tell of others from their world easily. That may be something you need to keep a note of.
“If you got that, let’s start helping you with spring boot and maybe the version control we use here, Git. What did you use back then?” Emory brings you to the table and started explaining.
“TFS.” You replied.
“I’m glad you’ve worked with version control before. At least you’re not a FOVC user.” Sneered Emory.
“FOVC?”
“Flash-disk Oriented Version Controlling. A few lunatic companies also used Google Drive™ for their version control. Be glad that your experience was with TFS.” Added Emory.
Spring Boot Basic
Note: Please prepare your environment before continuing to the next step.
- IntelliJ Ultimate
- Git
Supplementary tutorials are also available on SCeLe. Please keep in mind that the tutorial below is made with IntelliJ Idea Ultimate.
Creating a Spring Boot Project
“Try opening Spring Initializr
on the new project
menu on your IDE. Fill it with what I wrote here.”
Emory showed you a few configurations they used to make a Spring Project. “Of course, you can pick whatever location you want. Use a project SDK with the same or higher version of Java than you picked. You can also do this outside of your IDE by visiting Spring Initializr .”
“You’ll get the following application structure.” Emory showed you the structure you get from using Spring Initializr
.
“I’ll explain some folders you need to know.”
- The
src
folder has two important sub-folders:main
andtest
. As the name goes,test
will be where your test files go andmain
will be where your main application goes. \ Themain
folder will also contain two other folders,java
which includes your java code andresources
which contains your other assets for the web, like static files, HTML templates, and configuration inside ofapplication.properties
. Some of the configurations you know from Django, like database, are in that file on Spring. gitignore
is a file that contains all the other file names that you don’t want to commit on your version control.-
Gradle files. There are four important ones:
build.gradle
,gradlew
,gradlew.bat
, andsettings.gradle
. You probably don’t need to mess withgradlew
and the bat file. So we’ll focus onbuild.gradle
andsettings.gradle
-
The
build. gradle
file contains Gradle tasks, application information, configurations, plugins, and dependencies. The Java version used can also be controlled in this file. In Python, you might be used to putting dependencies on ‘requirements.txt’ or ‘Pipfile’. But on Spring Boot or other Gradle-based apps, it’s usually in ‘build.gradle’. - The
settings.gradle
is where the Gradle module is configured. In this case, you can see the name of the module. For advanced use, like on a multi-module Gradle project, you will use this file to activate sub-modules.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
Basics of Model-View-Controller on Spring Boot
“Are you familiar with the Model-View-Controller or MVC?” Emory continued their explanation of the structure design and its effects on the application.
“I have experience with MVT before in Django.” You replied.
Emory looked relieved. “Okay, so this shouldn’t be that long.” They added.
“Model-View-Template or MVT on Django is fundamentally a derivative of MVC.
The design pattern is created to suit its use on Django.
The difference lies in the view
part, ironic because they have the same name, right? View on Django contains business logic that also manages requests and responses of the application.
View on MVC is a layer that manages the display of the app.
On Django, that’s the job of the Template
part. Long story short, MVT’s View
is Controller
and Template
is View
on MVC.
This is extremely simplified, I know. Up next, I’ll tell you what each layer does.”
Model
is a layer that represents data and business logic.Controller
is a layer that manages requests and responses of the application. Ideally, this layer shouldn’t contain any business logic. It should focus on processing requests from users and returning the appropriate responses.View
is a layer that manages the display. In web applications, this layer contains files that bridge HTML files and static files like CSS and JavaScript. In reality, theController
layer also works together with this layer to serve the proper pages.
In Spring Boot itself, there are also a few extra layers to increase the maintainability and clarity of each layer.
You can see that the Model
layer has quite a big role.
In order to make the Model
layer have one specific job, it is divided into two other layers:
- The
Service
layer exclusively manages business logic. - The
Repository
layer exclusively manages data processing
And just like that, the Model
layer’s job is only to represent data.
Basics of Requests and Responses on Spring Boot
“Next up, let’s try making a simple web application.” Emory started typing on their IDE. “Try arranging some packages like this. Each package will represent a layer on Spring Boot’s MVC.”
“We’ll start by making a Controller. A controller in spring boot is a class that is given a @Controller
annotation.
Try making a simple controller that returns an HTML page first.”
Create a BaseController
class inside the controller
package.
Fill it with the code shown below.
Try to not write import statements manually.
Take the advantage of your IDE.
“Spring Boot now views the BaseController
class as a Controller.
A Controller class usually has a few methods.
These methods will represent a few different URLs.
The method index in the BaseController
class is an example.
That method has the @RequestMapping
annotation.
This tells Spring Boot that it handles an endpoint.
There are a few parameters that you need to know, method
and path
.
The method
parameter describes which HTTP Method the method itself will accept.
In this case, it’s GET
. The path
parameter, on the other hand, describes the URL that it will handle.
The method’s name itself doesn’t actually do anything, but try to give it a proper name that describes what it’s supposed to do.
Lastly is the return type of a Controller’s method.
Every single one returns a string.
This string you return will be a name of an HTML file you have in resources/template.
You can see here the index method returns home
, meanwhile the template folder does not contain a home.html
file.
So we need to create it.”
Make a home.html
file in resources/template
Fill it as such:
Now try running the application. Open Tutorial0Application
and click the run button.
If there’s no problem, the IDE’s command line will look like such:
And the result will be as such:
“Now try adding two other methods in BaseController
.”
Emory points at the @GetMapping
notation on both methods.
You noticed it’s different from the @RequestMapping
you used on the index
method.
“Did you realize something?”
You nodded. “Is GetMapping
a RequestMapping
that accepts the HTTP method GET
?”
Like always, Emory confirms your guess with her gestures. “We wrote it this way so it’s more concise. “But besides that, there are other uses for RequestMapping
called URL Grouping.
It’ll let you group a bunch of URLs with the same prefix, such as student/create
with student/list
.
You will need to utilize this in the application you were asked to make.”
In the two other methods, there are also two other annotations and a model
parameter as an argument of it.
"Next, let’s use RequestParam
and PathVariable
.
These two parameters are important to handle the URL mapping.
Maybe it’ll be easier to show you an example.
Because we have these methods, there’s a slight change we need to make to the HTML file.
Try changing it like this!"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
"th:if
and th:unless
are if and else statements in the Thymeleaf templating engine.
Since you used Django, I’m sure you are familiar with these terms, right? Here you can see that there’s a check done to the variable name
.
You may notice that this is a variable that the model
parameter puts.
Pay attention to model.addAttribute(“name”, name);
.
Basically, model
contains key-value pairs.
In our case, the HTML calls on the key value name
, and it returns a Java object as a value which happens to also be called name.
Surely you’ve used dictionary on Django before for something like this.
So, you can just think of this model
here as a dictionary on Spring Boot.
Also, bear in mind that this model
isn't the same model as the one in MVC."
Now try to rerun the app and open http://localhost:8080/greet?name=Emory
, you should see the following result:
You can substitute Emory with whatever you want. Try changing Emory to your own name and see the result.
“Compare the result with this.” Emory urged you to open http://localhost:8080/greet/Emory
“Any difference?” Emory asked.
You can see a few differences in the URL pattern used.
“I’ll answer based on what I see.” You started. “The first one is the use of RequestParam
, noted by ?paramName
, or in this case, ?name
.
Another one is the PathVariable
noted by the /greet/{variableName}
, or in this case, name
.”
Emory didn’t say anything, but they look satisfied with you. You take that as a sign that you were right.
“At this point, you’ve created a basic function on Spring Boot. It may be about time that you start committing your progress to git.”
Right now, your Spring folder from Spring Initializr
isn’t considered a git folder yet. To designate a folder as a git folder, use the command:
1 |
|
You can check what things have been done (in this case, what has been added to the folder outside of the ones in ‘gitignore’) to a git folder with the command:
1 |
|
To add a file to git, use:
1 |
|
If you want to add all files to git, you can use the following command. Just make sure everything in ‘git status’ is what you want to add. The best practice is to add and commit in as small of a chunk as possible. You will learn how to do this later.
1 |
|
You can use git status
again to check which files have been added to git.
Then, you just need to commit your addition with the following command:
1 |
|
For now, do a commit with the message “initial commit” as shown below:
1 |
|
First Task Implementation
Emory analyzes the documents Rory gave you. They look uninterested to the point of boredom. After a few seconds of flipping the pages back and forth, they returned it to you.
“Rory always gives the same task to every new recruit.” Emory lamented.
“Okay. As you can see, this application is a prototype of a teaching assistant information system. This application is made for a small university at the outskirts of Prediff.”
“Prediff is an outlaw town west of the trade city of Yukginia, right?” You asked. Emory only nodded slightly.
“With that said, Rory only asked to make a simple version of that app. Luckily, Rory also gave you the detailed requirements. You’re asked to make a page that could create a new ‘Student’ and show it on another page. You also need to repeat that for ‘Course’. I’ll help you make the ‘Student’ page, but I want you to make ‘Course’ on your own. It just so happens that only I can help you this far.”
“Thank you so much.” You’re very thankful that Emory agrees to help you finish your task. At least you still have a kind senior among your other co-workers.
1 2 3 4 5 6 7 8 9 |
|
First, we need to change the requirements into code.
The easiest step is to make the model or core of the application first.
Make a Student
class inside the model package.
But before you do that, let’s make a new branch on git.
“The reason why we should make a new branch is as I said earlier, we should make each of our changes focused and minimal.
We also want long-lived branches, like master
, to only be used for mature codes.
Maybe you can find other usages from branching.
I’m serious, I will ask this later.”
Make a new branch called task-implementation-student
with the command:
1 |
|
Or in this case:
1 |
|
After that, you can start on the model like so:
Generate setter and getter. On IntelliJ, you may use right-click -> generate -> setter and getter or use the alt+insert shortcut (On Linux and Windows). Try using the shortcut now on your machine.
“Ah, speaking of which, to reduce boiler code, we will use Lombok. If you remember, it’s part of the dependencies I asked you to put in the beginning. Delete the setter and getter you’ve generated and replace it with the following code.”
The next step is to make the Repository
layer.
“I taught you the simple version of model
and repository
. In truth, you would want to integrate both layers with the database. Let’s make a simple 'database' with the following data structure.”
This class is essentially a regular Java class.
We haven’t used the Repository
feature that connects it to the Spring Boot database.
The main thing you need to note is the @Repository
annotation.
Simply put, it serves the same purpose as @Controller
, showing that a class is a repository. By tagging this class as a repository, it will become a Bean
that will be used a lot in Spring Boot.
Next, create a service of Student
. First, make the interface StudentService
inside the service package, fill it as such:
“So, do you remember there are some things you need to check on the Student
business process? There’s a need for validation. Let’s make an exception in case there’s a duplicate Student
name. Make a new package called exception
and make a class called DuplicateStudentnameException
.”
1 2 3 4 5 6 7 8 |
|
Now that the preparation is done create an implementation of the StudentService
interface. Make another class, StudentServiceImpl
, inside the Service
package.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
|
“Pay attention to @Service
and @Autowired
. I’m sure you can guess what @Service
does at this point. Let’s focus on @Autowired
.
@Autowired
is a dependency injection mechanism on Spring Boot. In this case, we didn’t explicitly initialize StudentRepository
. @Autowired
tells Spring to make an instance of StudentRepository
. This is only possible on a Bean
. Remember that previously we gave the @Repository
annotation to StudentRepository
.
That turns it into a bean that can utilize @Autowired
for its initialization process. After this, you will see the same for StudentService
on the controller.
Now let’s make an implementation of the StudentController
class inside the Controller package.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
|
“I’m not going to explain everything again. I’m sure you’re now quite familiar with a lot of these codes. Our focus this time is to make a form for Student
. Pay attention to the createStudentPage
and createStudentPost
methods.
But, before that, let’s make an implementation for studentList.html
and createStudent.html
.”
studentList.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
createStudent.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
The Student
creation process is divided into two methods, represented by the aforementioned methods.
The createStudentPage
method has an HTTP GET method and serves to direct users to the form page of Student
.
While the createStudentPost
method has an HTTP POST method and serves to submit the form to the backend.
The form submission process is also split into two parts that you need to know.
Take a look at the createStudentPage
method!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
"Now try doing another add and commit. But let's utilize a feature in our IDE."
Open the git
menu on IntelliJ and open commit. The following window will show up:
You can see the list of files given is the same as what you get from doing git status
.
The changes
window on your IDE might be different. Maybe you find that the files you made haven't been added yet. If so, please check the unversioned files
section.
Pick files related to the Student
implementation that we have done, and now we're going to write a commit message.
Write down Implement student page
inside the commit message text box and click commit. There may be a warning sometimes. For the purposes of this exercise, proceed with commit anyway if a prompt does show up.
You need to follow a few rules in writing a commit message. Try reading the following article, How to Write Git Commit Message, to learn more about the rules.
Some Advanced Git
Emory were looking at your program for a few moments.
“Alright, I don’t see any problem.” They commented. “Now, try pushing it to your repository. Oh, and don’t forget to push the master
branch first. I assume you know how to make a repository on Gitlab and how to configure your local git (hint: git remote
). Give it a descriptive name.”
Switch to the master branch. You can use the GUI inside IntelliJ or do it through the command line.
1 |
|
Push your commits. You may also use the GUI inside the git menu on IntelliJ or use git push
on the command line.
Go back to the task-implementation-student
branch and make another push. Look up Merge Request
for git.
Make a merge request to the master branch from the task-implementation-student
branch. Try merging and watch what happens. You will be asked to explain this later.
“Now, let’s simulate the use of ‘git reset’ and ‘git revert’.”
Git Reset
Make a MockStudentServiceImpl
inside the Service package and fill it as such:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
StudentService
type. This causes Spring to not know which bean to use. You can fix this problem by changing @Autowired
on StudentController
to a @Qualifier
and explicitly choosing StudentServiceImpl
.
But for the purpose of this tutorial, we want to fix the issue by turning our repository into a previous commit version with git reset
.
You can learn more about Qualifier
to understand how to handle two conflicting bean types.
As usual, you can use the IDE’s built-in feature to do this, but it’s best if you learn how in a command line first. (Hint: Try clicking on the git menu on the bottom left part of your IDE to explore other git features)
Run the following command to see what commits you have done:
1 |
|
The command line should look like this:
While the IDE should look like this:
We’re going to solve this by using the command line. For the IDE solution, please try it yourself.
You know that your application works on the Implement Student Page
commit.
Now let’s do a git reset
back to that commit. Copy the commit has from the Implement Student Page
commit. Note: Your commit hash will be different from the given image.
The basic git reset syntax is as follows:
1 |
|
Example (Again, this is an example. Your commit hash will be different. Do not copy-paste the following example. Copy the hash from your git log
instead)
1 |
|
Now, if you do git log
again, you can see that your MockStudentService
commit is gone. Try rerunning the application to make sure it works. (Pay attention to the --hard argument. Is there any other option? Do your own research!)
Git Revert
Create a new branch called simulation-revert
.
Re-add the MockStudentServiceImpl
again as in the previous section.
Do a git add
, git commit
, and git push
.
Try simulating git reset
again and do a push.
You will find that said push is denied by git. This is because your remote repository does not have a commit ahead of your local repository.
You cannot do a push unless you use git push –force
(For the love of god, don’t do try this at home).
In this state, it’s better to use git revert
.
First, do a git pull
to get the changes that you’ve done to your remote repository.
Open the git log
again. Contrary to git reset
, we’re not going back to a commit where the problem has not yet arisen, but we’re canceling a problematic commit.
As such, copy your MockStudentService
implementation commit’s hash.
Do:
1 |
|
Example:
1 |
|
You will be asked to do a commit message. Fill it with a good description.
The result will look as such:
You can see the revert process adds a new commit that cancels the previous commit. Do another push and come back to the task-implementation-student
branch.
End of Your First Day
“How was it?” Asked Emory. They look like they finished their task today. Her cold eyes contrasted the close attention they gave you. You’re still trying to complete your remaining tasks to implement the Course
page.
“Not so bad.” You commented.
“Okay then, good luck.” Emory looks indifferent. They started packing their belongings. Emory is going home, you thought. “Don’t forget the things I’ve taught you. Rory and the boss might want to evaluate everything, from your code quality to git discipline.”
Emory then walks toward your desk, pulls up a chair, and sits beside you. You stare at Emory with confusion.
“I’m going to rest up here for a bit. Poke me if you have any questions.” Mentioned them.
“Ah, thank you.”
“Don’t be too long now. I’ll be taking you around the city.” Followed Emory, still emotionless as ever, their actions directly oppose their cold tone. “It’s been a long time since I’ve met someone from my world. I would like to know what’s been happening out there.” They continued.
“Roger.” You responded.
Your first day ended with a short trip to a few places with your ice-cold senior. Their face continues to be impassive, though you feel like their mood slightly improved from when you first met them. You smiled. This wasn’t a bad way to end your first day. You made small talks with Emory under the dimly lit moon. About this world, about 0, and about other people from your world. If possible, you would like to meet them all. Their stories, whether they have any regrets leaving, or maybe whether they want to come back if given a chance.
This is the start of your story. You who have been sent to another world to work.
Tasks
- Read the entire tutorial
- Do everything the tutorial asks
- Implement
Course
feature according to the requirement
Hints
- You can follow how the
Student
feature is implemented to work on theCourse
feature - Make sure you follow a good Git discipline for
Course
- Make sure you take note of every single time this tutorial tells you to study up on something. You will be asked about them on the demonstration session later
Created: 2022-02-08 21:14:01