Category Archives: Discussions

A Strange Way to Use Get Requests

Strap in because this post is going to get very anecdotal.

Backstory

I have a history of running Minecraft servers for my friends and I. A few years ago, I learned how to port-forward a locally hosted server and use it to play on. While it’s not the most secure thing in the world technically, it works really well and it’s produced a lot of fun. For whatever reason, I was thinking about it again recently.

When I’m out of school, that’s usually when we play. I’ve slowly been learning more and more. I’m currently at the point where I can make intermediate datapacks for the game and use shell/bash/batch scripts to run the server. Over the summer for instance I created a shell script to run the server, back it up, and reload it if it crashes.

There’s still one major problem with my servers, however. I need to manually turn on one of my computers and run it. Then that computer has to stay on until I want the server off. It might waste power if no one is using it (also increasing the risk of the world becoming corrupted) and it’s just slowly going to wear out my hardware.

Recently, I remembered that I had two old laptops. Unfortunately, the newer one didn’t have a power cord. So I broke my way in and took out the ram, hard drive, and wifi card. Then I swapped those components into the other laptop. Lastly, I installed Lubuntu onto it. It works surprisingly well. I then set up NoMachine so I can remote into the machine without having it in front of me. The BIOS supports wake on LAN so I took a few hours to get that working. Now, I can leave that laptop plugged in next to my router and send a signal over the internet to wake it up. While the router blocks the magic packet required on ports 7 and 9, a simple port forward allows wake on LAN to work from anywhere. I would definitely not recommend that for most scenarios, but until I find myself the victim of attacks on my router, I think I’ll take my chances.

Now, my goal has been to create programs that run all the time that laptop is running to be able to receive requests to launch Minecraft servers. I’ll work out a script later for handling crashes and such, as well as a datapack for automatically stopping the server when no one has been online in 30 minutes or so. So I started work on a node server.

Node.js

While I am learning about node in my CS-343 course, I have already taken the Web Developer Bootcamp by Colt Steele on Udemy and I highly recommend it. This is the basis of my server so far:

const express = require("express");
const app = express();

const server = 
app.listen(process.env.PORT, process.env.IP, function() {
     console.log("The server has started.");
});

var minecraft_server1_on = false;

app.get("/minecraft/server1/start", function(req, res) {
     res.send("Turning on the server…\n");
     minecraft_server1_on = true;
});

app.get("/minecraft/server1/ping", function(req, res) {
     res.send(minecraft_server1_on);
});

app.get("/minecraft/server1/declare_off", function(req, res) {
     res.send("The server is off.\n");
     minecraft_server1_on = false;
});

app.get("/exit", function(req, res) {
     res.send("Exiting…\n");
     server.close();
});

app.get("*", function(req, res) {
     res.send("The server is running.\n");
});

Now, I’m certain that I’m making mistakes and doing things in a strange way. It definitely is not in a state I would use for anything other than a private server, and even then I’m still working on it.

Here’s the important parts. It’s an express app with a few get routes. I’m running this server from a bash script using nohup so that it can simply run in the background while the pc runs. However, I want to be able to stop the server from another bash script without using process ID’s so I don’t risk closing the wrong thing. While I was considering my options, I thought of something really interesting. I can use the curl command to perform a basic get request in a bash script. So I created a route /exit that when requested, it shuts down the server.

It’s incredibly simple and there are definitely ways around it, but I never even thought of using get requests in this way. There is information in the requesting of a web page, excluding the normal stuff. Just the fact that a request occurred can be useful. What this means is I can check if the server is running by pinging most routes. I can also both send and receive boolean data without any real complexity. Once again, I’m sure this violates some design principle. However, for something like this that is meant to be mostly casual and private, why should I need to set up proper post routes and databases when I can use this.

My method of turning on a Minecraft server now; I store the state in a variable in the node server. This is fine because when this server stops, all other servers should have stopped so I don’t need a database. Then, by pinging certain routes, I can turn a Minecraft server on, check if it’s on, and declare that I have turned it off somewhere else. The node server can maintain the state of Minecraft servers (I can possibly run multiple on different ports) as well as handle inside and outside tracking.

Keep in mind again, I’m looking for the easiest way I know how to make this work right now, not the best way to do it. So from here, I had no idea how to make the node server actually start a Minecraft server. I know how to run one from a bash command though. So I created a C++ program that will also run all the time. It can periodically check the status of the node server. For instance, if I send a request to the node server to turn on a Minecraft server, the C++ program can detect that change by running system("curl http://localhost:PORT/minecraft/server1/ping"); Once again, I’m using a UNIX command in C++ rather than using a wrapper library for curl because it was an easier solution for me. The node server can then return true or false. In fact, the C++ server won’t directly run the command. It will run a bash script that runs the command and stores output into a file. C++ can then read the file and get the result.

I’m currently still in the process of making this work. After this, I’ll make another node server hosted on Heroku that has a nice front end to allow myself and other people to request the laptop to wake on LAN, and then directly interact with those local node server. I may even make a Discord bot to allow people to simply message in chat to request the server to turn on.

Conclusion

Once again, I do not recommend anyone actually does this the way I have. However, the whole point of coding is to make a computer do what you want it to. If you can hide the get requests behind authorization (which I will probably do) as well as fix any other issues, this could be useful. It’s not even specifically about using get requests in this way. Abstract out and realize that it’s possible to do something in a way you never thought of, and it’s possible to use something in a way you never have. Consider what you know and explore what’s possible. Figure out whether or not it’s a good practice based on what problems you run into. I think that’s one of the best ways to learn and if you can find a functional example to fixate on, the way I have, you can find yourself learning new things incredibly quickly.

From the blog CS@Worcester – The Introspective Thinker by David MacDonald and used with permission of the author. All other rights reserved by the author.

Don’t Spend So Much Time Coding Cleanly!

There comes a point in every developer’s career where they transition from “make it work” to “oh my God I need to make this look decent”. Initially, our goal is to create a functional Hello World program. However, as we develop, we slowly begin to learn proper code styles and naming conventions. After reading enough Stack Overflow Forums, we start to become self aware of how our code looks and we begin to focus on code aesthetics. While there’s merit in that, we often focus on the wrong things.

This video does a great job of explaining just that: there isn’t really any such thing as clean code. Now, that isn’t to say that there aren’t wrong ways to code. I’m sure we can all name plenty. That being said, the main point is that we shouldn’t spend our time trying to code perfectly the first time.

The best way to code is to do so as well as we can without spending too much time overly focused on getting everything right the first time. If you know you have the opportunity to do something right or cut corners, do it right. However, if you’ve spent 10 minutes trying to name a variable, give it some placeholder name and worry about it later. The first priority is functionality. Later on, you can review and refactor your code.

The main goal of refactoring is readability. In a compiled language especially, there is only so much efficiency the programmer can add. Compilers do a remarkable job of optimizing code by themselves, so your main goal should be readability. Make sure that other developers, as well as your future self, can read and understand your code. Add comments where necessary, but aim for self-commenting code. If your code is its own comment, that helps save space.

In conclusion, focus on simple and readable code. Don’t waste your time doing something that can simply refactored later, within reason. With that being said, try to do things right the first time if it’s obvious how to do it right.

From the blog CS@Worcester – The Introspective Thinker by David MacDonald and used with permission of the author. All other rights reserved by the author.

Adapter Design Pattern

I’ve always found Derek Banas’ channel really useful. In late middle school, I started watching his tutorials for how to code. So it’s really interesting to go back and watch his videos, to say the least.

I feel like the adapter design pattern is something that shouldn’t really need to be used. Don’t get me wrong, it’s very useful. Like real adapters, however, the problem itself shouldn’t really exist. That’s especially true with code; it seems as though adapters become required when interfaces aren’t abstracted well enough. In his video, for example, he has an EnemyAttacker interface that represents some kind of enemy. However, the methods are very specific and presume certain characteristics about the attacker. We then need to use an adapter to get around that specificity. It seems to me that writing the interface more generally to begin with would be more ideal. But given that it’s a bad idea to modify old working code, an adapter is a great solution.

In principle, an adapter does exactly what you expect it to: it adapts code. It takes one “interface” and connects it to another “interface”. That’s the colloquial interface as opposed to a coding specific interface. We use adapters every day. The best example is a phone charger. It converts (or adapts) 120V AC power to a low DC voltage. It also adapts the physical plug into USB type-c. All of the functionality is hidden inside of the charger and from the perspective of a user, it’s literally plug and play.

An adapter in code acts the same. I honestly like the example he gave so if you want to see an example of actual code, check out his video. Conceptually, one description of an adapter is the following: We have two interfaces A and B that have many differences, but are conceptually similar. We can create an adapter so we can use any A as a B, or vice versa. It’s okay because of their similarity (or perhaps they need not even be similar!). Really, it’s an incredibly basic pattern so the specifics aren’t that important.

Fundamentally, an adapter is just code that allows other code to operate together. Again, I think the best way to conceptualize it is through the imagery of any real life adapters. However, it should ideally not be necessary in scenarios such as the one from the video. Abstraction, within reason of course, should be prioritized ahead of time.

From the blog CS@Worcester – The Introspective Thinker by David MacDonald and used with permission of the author. All other rights reserved by the author.

Introductory Post for CS-343

Welcome! First I would like to point out that all posts for this course should all be placed in roughly the same categories. However, they all will be tagged with CS-343. This should make them easy to find.

These posts will be centered around me searching for online materials other people have posted that relate to the core topics of CS-343. I will then be sharing them, interpreting them, etc. It will be a collection of information primarily useful to the following topics (as taken from the course syllabus):

  • Design Principles
    • Object Oriented Programming
    • SOLID
    • DRY
    • YAGNI
    • GRASP
    • “Encapsulate what varies.”
    • “Program to an interface, not an implementation.”
    • “Favor composition over inheritance.”
    • “Strive for loosely couples designs between objects that interact”
    • Principle of Least Knowledge
    • Inversion of Control
  • Design Patterns
    • Creational
    • Structural
    • Behavioral
    • Concurrency
  • Refactoring
  • Smells
    • Code Smells
    • Design Smells
  • Software Architectures
    • Architectural Patterns
    • Architectural Styles
  • REST API Design
  • Software Frameworks
  • Documentation
  • Modeling
    • Unified Modeling Language
    • C4 Model
  • Anti-Patterns
  • Implementation of Web Systems
    • Front End
    • Back End
    • Data Persistence Layer

Hopefully, these posts provide you with many resources to help you learn these topics for the first time or to help you recall them after a long time has passed! I wish you the best of luck in whatever you’re hoping to achieve!

From the blog CS@Worcester – The Introspective Thinker by David MacDonald and used with permission of the author. All other rights reserved by the author.