Horizontal Formatting and Tricks By albro

In the previous post, I showed you the following code and explained why you should do vertical spacing or vertical formatting:
const path = require('path');
const fs = require('fs');
class DiskStorage {
constructor(storageDirectory) {
this.storagePath = path.join(__dirname, storageDirectory);
this.setupStorageDirectory();
}
setupStorageDirectory() {
if (!fs.existsSync(this.storagePath)) {
this.createStorageDirectory();
} else {
console.log('Directory exists already.');
}
}
createStorageDirectory() {
fs.mkdir(this.storagePath, this.handleOperationCompletion);
}
//Continuation of codes
The only rule I told you about this was that vertical spacing should separate unrelated concepts (for example, we should separate methods in the above class using whitespace), but what about related concepts? Is it correct to convert the code above to the code below?
const path = require('path');
const fs = require('fs');
class DiskStorage {
constructor(storageDirectory) {
this.storagePath = path.join(__dirname, storageDirectory);
this.setupStorageDirectory();
}
setupStorageDirectory() {
if (!fs.existsSync(this.storagePath)) {
this.createStorageDirectory();
}
else {
console.log('Directory exists already.');
}
}
createStorageDirectory() {
fs.mkdir(this.storagePath, this.handleOperationCompletion);
}
insertFileWithData(fileName, data) {
if (!fs.existsSync(this.storagePath)) {
console.log("The storage directory hasn't been created yet.");
return;
}
const filePath = path.join(this.storagePath, fileName);
fs.writeFile(filePath, data, this.handleOperationCompletion);
}
handleOperationCompletion(error) {
if (error) {
this.handleFileSystemError(error);
}
else {
console.log('Operation completed.');
}
}
handleFileSystemError(error) {
if (error) {
console.log('Something went wrong - the operation did not complete.');
console.log(error);
}
}
}
const logStorage = new DiskStorage('logs');
const userStorage = new DiskStorage('users');
setTimeout(function () {
logStorage.insertFileWithData('2023-09-21.txt', 'A first demo log entry.');
logStorage.insertFileWithData('2023-09-22.txt', 'A second demo log entry.');
userStorage.insertFileWithData('albro.txt', 'Albro Hive Blockchain');
userStorage.insertFileWithData('ocdb.txt', 'OCDB Hive Blog');
}, 1500);
This sample code is an unreadable code because all the lines are separated from each other and it's difficult to distinguish which of them belong to a particular method at first glance. Therefore, just as the absence of space on the vertical axis is bad, its excessive presence will also be bad and harm the readability of the code. Another point is that you should always keep related concepts close together. For example, the setTimeout
function from the code above is a related concept or code category, so it should be written as follows:
setTimeout(function () {
logStorage.insertFileWithData('2023-09-21.txt', 'A first demo log entry.');
logStorage.insertFileWithData('2023-09-22.txt', 'A second demo log entry.');
userStorage.insertFileWithData('albro.txt', 'Albro Hive Blockchain');
userStorage.insertFileWithData('ocdb.txt', 'OCDB Hive Blog');
}, 1500);
As you can see, there is no space between the lines of this code because they all do a specific task together and are not separate.
The process of reading the code
Before I want to go into the horizontal formatting discussion, I have to explain a special point. In the above code (DiskStorage
class), it has been tried to define related methods as close as possible. For example, the handleOperationCompletion
method is defined right next to the method that uses it:
insertFileWithData(fileName, data) {
if (!fs.existsSync(this.storagePath)) {
console.log("The storage directory hasn't been created yet.");
return;
}
const filePath = path.join(this.storagePath, fileName);
fs.writeFile(filePath, data, this.handleOperationCompletion);
}
handleOperationCompletion(error) {
if (error) {
this.handleFileSystemError(error);
} else {
console.log('Operation completed.');
}
}
You should also try to bring related methods and functions together as much as possible. Why? Because if someone is reading the code, they can easily find the definition of a function and not have to scroll to the end of a few hundred lines of a file.
The explanations I gave about this were general and for all programming languages, but some of you may have a question about how we called the method first and then defined it? In a language like JavaScript, you can do this because JavaScript has hoisting capability, that is, it loads the definition of variables and functions first and then executes the rest of the code, but in languages like Python, by doing this You will have a problem. Consider the following example:
start();
function start() {
console.log('start');
next();
}
function next() {
console.log('next');
last();
}
function last() {
console.log('last');
}
If you run the javascript code above, everything will run smoothly; It means that first the start
method will be executed, then the next
method will be executed, and then the last
method will be executed. Now consider the following example from the Python language:
# do't work
# start()
def start():
print('Start')
next()
# don't work
# start()
def next():
print('Next')
last()
def last():
print('Last')
# Work
start()
I have left a comment in this example for you to see in which places calling the start
function will work. By looking at these codes, you will notice that calling the start
function only works at the end of the file and after defining the functions, and we get errors in other cases. Anyway, in my opinion it's better to keep related functions as close together as possible and also if possible, define the function or method before using it even if you have hoisting because it's more readable. This is partly a matter of taste.
Horizontal Formatting
Horizontal molding, as the name suggests, is related to molding along the horizon line. what does it mean? That is, in horizontal formatting, all our focus is only on one line and its length. The general rule of thumb in horizontal formatting is that other programmers should be able to read your code without scrolling horizontally. Horizontal scrolling occurs when the length of your code lines (the number of characters per line) is too long, so it protrudes from the page and we have to scroll horizontally to read it.
The first rule to solve this problem is not to write long codes in one line. For example, consider the following code:
code>class DiskStorage { constructor(storageDirectory) { this.storagePath = path.join(__dirname, storageDirectory); this.setupStorageDirectory(); } }
This is the same DiskStorage
class, but this time I wrote the constructor along with the class definition in one line and didn't use indentation. I don't think I need to explain why such code isn't easy to read. Whenever you notice that your codes are getting too long, it is better to break them and put them on a new line.
Our second rule for horizontal formatting is to use indentation. Note that in some programming languages such as Python, the use of indentation is necessary, but in languages such as JavaScript it is not necessary and you can write thousands of pages of code in one line! But you should never do such a thing. Consider the following example:
const path = require("path");
const fs = require("fs");
class DiskStorage {
constructor(storageDirectory) {
this.storagePath = path.join(__dirname, storageDirectory);
this.setupStorageDirectory();
}
setupStorageDirectory() {
if (!fs.existsSync(this.storagePath)) {
this.createStorageDirectory();
} else {
console.log("Directory exists already.");
}
}
createStorageDirectory() {
fs.mkdir(this.storagePath, this.handleOperationCompletion);
}
insertFileWithData(fileName, data) {
if (!fs.existsSync(this.storagePath)) {
console.log("The storage directory hasn't been created yet.");
return;
}
const filePath = path.join(this.storagePath, fileName);
fs.writeFile(filePath, data, this.handleOperationCompletion);
}
handleOperationCompletion(error) {
if (error) {
this.handleFileSystemError(error);
} else {
console.log("Operation completed.");
}
}
handleFileSystemError(error) {
if (error) {
console.log("Something went wrong - the operation did not complete.");
console.log(error);
}
}
}
const logStorage = new DiskStorage("logs");
const userStorage = new DiskStorage("users");
setTimeout(function () {
logStorage.insertFileWithData("2023-09-21.txt", "A first demo log entry.");
logStorage.insertFileWithData("2023-09-22.txt", "A second demo log entry.");
userStorage.insertFileWithData("albro.txt", "Albro is Happy in Hive Blockchain");
userStorage.insertFileWithData("ocdb.txt", "Hello OCDB");
}, 1500);
I have removed all the indentations in the above code and as you can see, this code has become many times more difficult to read and at first glance it seems like we have a very large function.
The third rule of horizontal formatting is to divide your statements into smaller statements. For example, in JavaScript (node.js) there is a function called mkdir
that creates a new folder and takes two arguments: the first argument is the address of the new folder and the second argument is a callback function that is executed after the operation is completed. Pay attention to the following code:
createStorageDirectory() {
fs.mkdir(path.join(__dirname, 'temp', '2023-3', 'images'), this.handleOperationCompletion);
}
To create the path in JavaScript, we must use path.join
to join the folders correctly, because the way of addressing is different in Linux and Windows (using /
and \
), so if you do the addressing manually For example, the codes are only executed on a specific operating system. The problem with the above code is that our statement is too long, that is, we have performed the operation of generating the first argument or creating the address in the same line, which has made this line too long. We could write the above code as follows:
createStorageDirectory() {
const storagePath = path.join(__dirname, "temp", "2023-3", "images");
fs.mkdir(storagePath, this.handleOperationCompletion);
}
The last rule of horizontal formatting is not to use very long and overly descriptive names. Naturally, the names of various methods and variables are a little longer than other code components, and this is completely normal, but it should not exceed a reasonable limit. Example:
createStorageDirectory() {
const storagePathForStoringImagesInATemporaryFolderFor2020 = path.join(__dirname, "temp", "2023-3", "images");
fs.mkdir(storagePathForStoringImagesInATemporaryFolderFor2020, this.handleOperationCompletion);
}
Choosing such a name, which is too descriptive, makes the codes crowded and unreadable.
Challenge and problem solving
Now that we are familiar with the concepts of code structure and formatting, it's time for a challenge and problem solving. I have prepared a python code for you that has some small problems and you have to solve these problems:
# (c) @albro / peakd.com
# *********
# Imports
# *********
from os import path, makedirs
from pathlib import Path
# *********
# Main
# *********
# A class which allows us to create DiskStorage instances
class DiskStorage:
def __init__(self, directory_name):
self.storage_directory = directory_name
def get_directory_path(self):
return Path(self.storage_directory)
# This function must be called before saving the file
def create_directory(self):
if (not path.exists(self.get_directory_path())):
makedirs(self.storage_directory)
# The desired folder must already exist
def insert_file(self, file_name, content):
file = open(self.get_directory_path() / file_name, 'w')
file.write(content)
file.close()
# Todo: Add error management system
log_storage = DiskStorage('logs')
log_storage.insert_file('test.txt', 'Test')
Note that the comments in the code above are not for you, but written by the developer. For example, in part of the code, we have a comment in the form of "Add error management system". I don't ask you to actually implement the error management system. Your task is to make the above code more readable based on the points I have explained before. Try to modify this code yourself and then compare your answer with mine. I say again that we do not have only one correct answer, but ways There are different ways to solve this problem.
I will start with the comments first. At first, we have a comment that identifies the author of the file and we explained that these comments are not a problem and are completely allowed. In the next step, we have comments that separate different parts of the file, and I explained to you that these comments are not appropriate at all. In addition, we have a comment that explains that the DiskStorage
class allows us to create an object from it! This comment is also a very bad comment because all classes are the same and this class does not do anything special. The explanations written in this comment do not work at all and are not even doc strings. To write documentation comments, which are known as doc string in Python, we must use three quote marks:
"""
the documentation goes here
"""
Therefore, these comments are not useful and we delete them:
# (c) @albro / peakd.com
from os import path, makedirs
from pathlib import Path
class DiskStorage:
Next, we had two other comments, both of which are considered warnings:
# This function must be called before saving the file
def create_directory(self):
if (not path.exists(self.get_directory_path())):
makedirs(self.storage_directory)
# The desired folder must already exist
def insert_file(self, file_name, content):
file = open(self.get_directory_path() / file_name, 'w')
file.write(content)
file.close()
If you look at these two comments, you will notice that they both point out the same issue. Calling create_directory
creates the directory, so it's natural that there must be a directory in that path before adding files (that is, create_directory
has been called). In my opinion, one of these warning comments is not a problem, but both of them are overwritten, so we have to delete one of them. We need to leave a comment next to the part of the code that will cause the error, so I leave the second comment:
def create_directory(self):
if (not path.exists(self.get_directory_path())):
makedirs(self.storage_directory)
# The desired folder must already exist
def insert_file(self, file_name, content):
file = open(self.get_directory_path() / file_name, 'w')
file.write(content)
file.close()
Our final comment is also a TODO comment that I have already explained how they work. The problem here is that instead of writing "Implementation of an error management system", it is better to actually implement an error management system and not postpone it to another time, but as a temporary reminder, there is no problem in using it, so leave it as well. we let. Also, in terms of vertical formatting, the codes have no problem and are considered readable, and the only problem they have is at the end of the file and the presence of a space between the two last lines of the code:
log_storage = DiskStorage('logs')
log_storage.insert_file('test.txt', 'Test')
These two lines are connected and adding a space to them is not interesting, so I'll remove this space. We should also listen to our warning comment and call the create_directory
statement before inserting the files. Also, another way to think about this is to say that an instance of a different class is created by performing different operations on the object, so these two lines should be separate:
code>log_storage = DiskStorage('logs')
log_storage.create_directory() log_storage.insert_file('test.txt', 'Test')
Whatever way you act, you must have a reason for it.
In terms of horizontal formatting, we are not a long line, but it is better to break the following line to make it more readable:
file = open(self.get_directory_path() / file_name, 'w')
In this line, we have created the desired file path, but everything is calculated as the first argument. Although this code is not bad, it can still be improved:
file_path = self.get_directory_path() / file_name
file = open(file_path, 'w')
So our final corrected code will look like this:
# (c) @albro / peakd.com
from os import path, makedirs
from pathlib import Path
class DiskStorage:
def __init__(self, directory_name):
self.storage_directory = directory_name
def get_directory_path(self):
return Path(self.storage_directory)
def create_directory(self):
if (not path.exists(self.get_directory_path())):
makedirs(self.storage_directory)
# The desired folder must already exist
def insert_file(self, file_name, content):
file_path = self.get_directory_path() / file_name
file = open(file_path, 'w')
file.write(content)
file.close()
# Todo: Add error management system
log_storage = DiskStorage('logs')
log_storage.create_directory()
log_storage.insert_file('test.txt', 'Test')
https://leofinance.io/threads/albro/re-leothreads-34je6vjwi
The rewards earned on this comment will go directly to the people ( albro ) sharing the post on LeoThreads,LikeTu,dBuzz.
Congratulations!
✅ Good job. Your post has been appreciated and has received support from CHESS BROTHERS ♔ 💪
♟ We invite you to use our hashtag #chessbrothers and learn more about us.
♟♟ You can also reach us on our Discord server and promote your posts there.
♟♟♟ Consider joining our curation trail so we work as a team and you get rewards automatically.
♞♟ Check out our @chessbrotherspro account to learn about the curation process carried out daily by our team.
🏅 If you want to earn profits with your HP delegation and support our project, we invite you to join the Master Investor plan. Here you can learn how to do it.
Kindly
The CHESS BROTHERS team
Thanks for your contribution to the STEMsocial community. Feel free to join us on discord to get to know the rest of us!
Please consider delegating to the @stemsocial account (85% of the curation rewards are returned).
You may also include @stemsocial as a beneficiary of the rewards of this post to get a stronger support.