Software Development: On A Need to Know Basis

A good clear principle for any software engineer and developer is that any class, method or function that you create and use should only have the bare minimum number of necessary arguments passed into it to correctly operate and not know more about the system than it should. Recently I have been doing some merge reviews and too many times I have seen the below case from both junior and (surprisingly) senior engineers:

...
Object object = getObject();
Date objectDate = getObjectDate(object);
...
private Date getObjectDate(Object object) {
    ObjectReader objectReader = new ObjectReader(object.getId());
    return objectReader.getDate();
}
...

As soon as I see the above I leave a comment on the merge request, something along the lines of “Why does the getObjectDate(Object) method need to take the entire object instance?“. This then forces the one who submitted the merge request to stop and think what is being done, and should it be refactored in someway.

In this case, the method only uses the object’s id to build a reader and get the date from the object. The actual object is not being used at all. Instead of passing the entire object into the method the id should only be passed in. There is less overhead. We should be seeing something like below:

...
Object object = getObject();
Date objectDate = getObjectDate(object.getId());
...
private Date getObjectDate(String objectId) {
    ObjectReader objectReader = new ObjectReader(objectId);
    return objectReader.getDate();
}
...

By only passing the bare minimum to the methods or classes then you are ensuring that your system does not know more than it needs to. By enforcing this rule, IMO you are ensuring that the system is:

  1. Cleaner – you know exactly what is being used and for what purpose.
  2. Safer – you are ensuring that only what you want to be manipulated can be manipulated and where.
  3. Modular – there are clearer separations between what needs to be done with what and where.

So when you are creating new classes or methods then consider what you are using as your arguments, what the method needs to do, and what exactly you need to pass in. Taking the time to logically structure your code and think through what is necessary for the method to do its job will save you massive headaches in the future. Short term pain, for long term gain 🙂

Moving to Visual Studio Code

I performed a clean install of Windows 10 on my Surface Book 2 recently and I have not installed my default go to Java IDE, which is IntelliJ. Instead I have now moved to using another tool, which I am finding is much more versatile and beneficial; Visual Studio Code. I have previously used Visual Studio Code but mainly as a way to edit my various data files such as XML, XAML, JSON, etc. and not any of my source code files like Java, C# or C++. I treated VS Code as a text editor only previously.

Visual Studio Code comes with a crazy amount of extensions which is great because that gives you options. To get started with Java, the extensions that I suggest you get is:

  • Java Extension Pack – this comes with all the necessary Java dependencies for Visual Studio Code such as proper language support for Java, Debugger for Java, Java Test Runner, Maven for Java.

On top of that extension you will need a JDK installed. If you want to know how to setup the environment for Java then have a look at the comprehensive page that Microsoft has created here. Microsoft also has a pretty sweet tutorial about how to build a Spring Boot application that can be found here.

One thing that IntelliJ made super simple was the compilation of Java code and managing all the dependencies, not to mention providing some really convenient debugging tools and project management. This makes it a really powerful development tool. When I was at university I primarily used a terminal or command console with a basic text editor for developing software, but as I moved towards writing commercial software for the company I work for I relied less and less on the terminal and command console and more on the IDE for the heavy lifting. Now that I use VS Code I am using the terminal and command console more again, and all of the necessary information such as the class path, dependencies, etc to ensure everything complies correctly is critical. Looking at this now, I really appreciate what the IDE does to simplify development process but realise how important it is to know the fundamentals.

I wrote about a similar scenario a month or so ago regarding Git (this can be found here) and how important it is to actually be really familiar with the Git commands through a terminal and/or command console because it is cross platform but it allows you to truly understand what is going on. Using a GUI is fine but all that does is issue the same commands you would use if you were using a terminal or command console. Using VS Code and the terminal to compile and execute my Java applications has allowed me to really appreciate what the IDE does to simplify the development process but also familiarise myself with the fundamentals and important concepts that can be carried between platforms.

 

Software Development: Writing Better Code Through Code Reviews

One of my favourite parts about being a software engineer is reviewing code. You get to learn alot about an individual from the code that they write and also learn how to potentially do something more efficient or understand a component of the application you had little exposure to before. If I look at a merge request, within the first few lines of code that is submitted I can get a good sense of how many years they have been programming and if they know what they are doing or if they just copied and pasted something from StackOverflow.

Graduate software engineers, entry level software engineers, or individuals who have just started programming, will often leave out some crucial elements such as appropriate null checks, logging, comments or appropriately named classes, methods and variables. There is nothing worse IMO then looking at some code and seeing a variable named “numbers”. It is most likely some collection object like a List and contains numerical values but offers little context in respect of the application it is used in. It may make sense to the person who wrote it but it probably won’t to others and you will most likely forget its context several months down the line. Red flags are very easy to spot here.

The more experience you get, the quality of the code that is submitted is generally far easier to read, is structured and broken down logically, has been optimised, there are the appropriate exceptions and null checks in place and the classes, methods and variables are named appropriately. But to get to this level you not only need to write a good amount of code but also look over and see how others are structuring and writing their code and do reading/research in your own time.

At work when I get a request to do a code review there are a number of elements I look at. Some of which include:

  1. Appropriate and meaningful class, method, and variable names.
  2. Small, compact and single purpose methods.
  3. Appropriate null and boundary conditional checks.
  4. Some level of optimisation on the operations performed.
  5. Meaningful unit and/or integration tests have been implemented.

At times I think that I am fairly harsh on the individual who submitted the code to be reviewed but then I think to myself that the better the code repository is in, the easier it will be to maintain and if good code practices are enforced then it will make everyone a better programmer. If I didn’t start being critical of my code and trying to better myself then when I do the code reviews I probably wouldn’t be as critical of theirs. Setting a high standard will only make the lives of software engineers working on the project much easier in the long run even if there is short term pain.

Artificial Neural Network: The Neuron

I am by no means an expert in machine learning or artificial intelligence, but just an avid learner and curious individual. Please use the information provided here as a supplement to further your knowledge and research.

I am currently building an artificial neural network from scratch (more specifically a multi-layer perceptron neural network. To help clear my head and make sure I understand everything correctly (or still remember from my machine learning subjects at university) I will be writing several blog posts about machine learning and artificial neural networks. To start the list of blog posts off I am going to write about one of the fundamental building blocks of the neural network, the neuron.

I will be skipping the background about the neuron and how it relates to the biological neuron. Instead I will cover how it is constructed and used in an artificial neural network.

Inputs

The neuron will process inputs from the previous artificial neural network layer. The previous layer could be:

  1. The input layer of the artificial neural network. In this case then the values are taken directly from the training data, test data, or user input when using the trained artificial neural network.
  2. A hidden layer of the artificial neural network. In this case the values would be outputs from other neurons.

Note: There is a special input which is called the “bias” which always has a value of +1. The role and purpose of the bias is so that there is a trainable constant and allows the activation function (will talk about that a little later) to give us the best possible chance of an optimal model. You can read some more about the bias purpose and use here and here.

Weights

For every input to the neuron there is an associated weight. Initially the weights are generally given a random value between the range 0.1 to 0.9. As the artificial neural network is trained the weights are adjusted as to better match the desired output.

Operations

Summation

The first operation to obtain the neuron output is to perform a summation of the multiplication of the associated weight and input. Mathematically this is represented as follows:

 

Artificial Neural Network Summation

 

where:

  • y is the output.
  • n is the number of inputs to the neuron.
  • i is the index of the input to the neuron.
  • w is a weight.
  • x is an input.

You may be asking, Chris why do we have the zero indexed weight and input outside the actual summation when you just add it anyway? Good question reader. Generally the zero indexed input is the bias which then makes the associate weight the zero indexed weight.

Activation

After the summation operation is performed there needs to be an activation function used. The use of the activation function allows for the enhancement or simplification of the neural network. Generally the activation function is non-linear and there are a variety of functions that can be used. Two of the most common activation functions are either sigmoid or rectifier functions. More information about the sigmoid function can be found here. More information about the rectifier function can be found here. The final value of the activation is the output of the neuron.

The next blog post would most likely be about the various layers of the neural network and how they are all interconnected. So stay tuned.

Git. Command Line or Graphical User Interface?

I was doing some reading today about Git and whether software engineers (or anyone else for that matter) should learn to do all their changes, etc for Git using command line or a graphical user interface. It was an interesting piece and some valid points were made for both using a command line and/or a graphical user interface. Me personally, I use a graphical user interface because it is extremely easy, hooks directly to the Git commands (under the hood) and can give you a nice visual tree of what the repository looks like. For your information Sourcetree is the client I use. However the more programming and development I do, the more I appreciate and want to learn what, how and why.

Some of the reasons why using the command line approach is valid and well worth it include but not limited to:

  1. Platform Independence:
    • No matter what operating system you are on, the commands are universal. So if you can use the Git commands in a Linux environment, then you will have absolutely no problem whatsoever doing it on a Windows or MacOS machine.
    • Git clients like Sourcetree for example are not available on every platform, and I imagine the other Git clients are also not available on every platform.
  2. Understanding:
    • This fundamentally for me is important and I think should be high on everybody’s list when using something.
    • By using the command line you get a level of understanding of what exactly you are doing, whereas using a graphical user interface this level of understanding (well to me) is abstracted and partially lost.
    • It also comes back down to point 1. If you understand what you are doing then you can take it to any platform.

Now using a graphical user interface is not the end of the world. Sometimes you just want to get something done and using a terminal if you are not comfortable with it can be extremely daunting. I personally would never be caught dead (well right now anyway) resolving merge conflicts and looking at diffs using a command line, and rebasing using a graphical user interface is so much easier.

I did some quick Googling and found what I feel are two really good resources that help and ease you into using the command line for Git. There is Try Git and Learn Git Branching. There are probably more out there but those are the two that I felt provide a good starting point. If there are others out there that you use or feel that there is a resource that is definitely worth reading then please add a comment below (sharing is caring) 🙂

Software Development: Returning Null and Null Checks

This past week I was looking over a number of merge requests and some of them had new methods declared with a return type of String (these are Java classes). With all of these methods if there is a logic issue or some unexpected behaviour then instead of returning an empty String object they all returned null. Personally this starts ringing alarm bells and waving red flags. Why is that you may ask?

If nulls are being returned, passed around to other methods, etc then the programmer will need to check before using that object (well they should anyway). There have been numerous times where I have seen programmers completely ignoring a null check for an object even though the method they used before to set that object could potentially return a null. With every one of these cases I politely leave a comment on the merge request, waiting until an update commit with the null checks are added before merging. Better safe than sorry.

Now am I being too cautious? I tend to lean towards the overly cautious side because it does not take much more lines of code and effort to ensure that the appropriate logging and checks are in place so that unexpected errors and problems with the software are not encountered by the user; plus it means that the software you are writing is safer. Let me know how you handle situations like this. Talking to some of the other programmers I know, they are split on the subject. Some don’t really care what is returned and don’t bother checking the object before use (those I call cowboy programmers), some don’t really care what is returned but do check before the object is used, and some care about what is returned and always check the object before use (I fall into this camp).

Potentially this problem is solved on a case by case basis. Is there a valid reason a null object should be returned? I’ll be doing some more reading about this to get a better understanding to ensure that I adhere to proper programming etiquette and safe programming.

My Artificial Neural Network Application & Podcast

The last month my blog has been fairly quiet.

I have been a little busy working on my artificial neural network, practising BJJ and playing some video games; plus I was sick for a couple of days. Initially my plan (which I stuck to for an extended period) was to put out a blog post every one to two weeks. However coming up with meaningful content that often can be fairly difficult.

This month I plan on writing about my artificial neural network with some emphasis on how a multi-layer perceptron works and how my application works/be used. It can be viewed on my GitHub page.

The current state of my artificial neural network on GitHub is just the skeleton with the majority of the code still not pushed to the repository. As I start to push the meat of the artificial neural network components such as the feed-forward, backward propagation, etc I will be creating specific blog posts.

The podcast that I was working on has not turned out as expected so I am in the process of re-evaluating the tools and topics that I will cover. I still plan on creating a podcast and with the new Content Creator version of Skype it should make the process  much simpler.

Git: GitHub & SSH Keys Setup

I have generated an SSH key a number of times, either at work or on my personal PC for a number of accounts. Now that I am using my Surface Book 2 as my primary development device until I get a new SSD for my desktop PC, I thought that it might be worthwhile documenting how to generate an SSH key and add it to a GitHub account.

Now if you already have an existing SSH key then you can go ahead and use that but if you have never generated an SSH key before or you may have forgotten how to then hopefully you will find this guide useful.

Assumptions/Pre-Requisites

  1. You already have Git installed on your device.
  2. You will be using GitHub for your repositories.
  3. You are using a Windows environment.

Step 1 – Create a new SSH Key

Do not proceed with this step until you have the pre-requites met otherwise this guide will not work for you unfortunately.

  1. Open your Git Bash Terminal.
  2. Execute the following command replacing <github email address> with the email address you use for your GitHub account:
    ssh-keygen -t rsa -b 4096 -C <github email address>

    The parameters used in the above command are:
    -t rsa – the type of key to create. In this case an RSA Key.
    -b 4096 – the number of bits in the key.
    -C <github email address> – a comment or label for the key.
    For more information about the parameters that can be used click here.

  3. You will be prompted to provide a file location where to save the SSH Key. Press Enter. This will save the file in the default location. Using the default location is recommended in this case.
  4. You will be prompted to enter a secure passphrase. If you choose to provide a secure passphrase then it will secure your SSH Key, this is a recommended step.

Your SSH key should now be generated 🙂

Step 2 – Adding your new SSH Key to the ssh-agent

If you have successfully performed the step “Step 1 – Create a new SSH Key” or you already have an SSH key that you want to use then you can proceed with the following step.

  1. Open your Git Bash Terminal (if you have closed it).
  2. Execute the following command:
    eval $(ssh-agent -s)

    This will start the ssh-agent in the background.

  3. Execute the following command:
    ssh-add ~/.ssh/id_rsa

    Note: If your key is not in the file named “id_rsa” or is not in the same location then you will need to replace the value id_rsa in the command with the name of the private key file and/or the location of where the file is store. The above example is for the default name and location.

Step 3 – Adding your SSH Key to your GitHub Account

The hard work is now all done. The next part is super easy even though there are more steps.

  1. Open your Gut Bash Terminal (if you have closed it).
  2. Execute the following command:
    clip < ~/.ssh/id_rsa.pub

    This will copy the content of your public key file ready to be pasted into GitHub. It is important to not add or remove any spaces or newlines to the content.

  3. Log into GitHub.
  4. Navigate to the “Settings” page.
  5. Under “Personal Settings” select “SSH and GPG keys”.
  6. Click “New SSH key”.
  7. Add a Title to your key. In this case for me it was generated from my Surface Book 2 so I made sure that it was referenced in the Title.
  8. Paste your key in the “Key” field.
  9. Click “Add SSH key”.

You should now see a new SSH Key added to your GitHub profile.

For more information generating your SSH Key, adding your SSH Key to your GitHub account, and other SSH connection information take a look at the GitHub Help Page. I have tried to simplify the process by combining the information that was scattered across two to three pages from the GitHub Help Pages into one page. The GitHub team have done a fantastic job in documenting the entire process however and the above link should be used if my steps are not sufficient or confusing in any way.

Returning to C and C++

Since the start of my third year of my Computer Science degree I have not really done much C or C++ programming. My primary programming language at the moment is Java and on the side I am doing some C# work. C++ was the very first programming language that I learnt by myself and during my bachelor’s degree it was the first language along with C that I was taught. There is some stuff that I really like and there is some stuff *cough* pointers *cough* that really annoy me.

With a fairly new laptop (my Surface Book 2), I thought it might be worthwhile to get back into some C and C++ programming. Java and C# are great programming languages but sometimes it is good to go back to your roots and program in a language that is significantly more low level. The attention to detail and level of understanding is significantly higher in C and C++, than Java and C#. If I ever start to feel lazy while programming in Java or C# I think back to how difficult it was to implement some things in C or C++.

I have Visual Studio 2017 installed on my Surface Book 2, but what I really want to do in C and C++ does not require the overhead for the projects that come with using Visual Studio. So instead I am going to use Cygwin (gcc and g++) instead. If you want to use Visual Studio then that is fine but to help others I am going to go into detail about setting up Cygwin so that you can run the gcc and g++ commands to compile and build your C and C++ programs.

Cygwin

Just like on the Cygwin web page “Get that Linux feeling – on Windows“, installing, configuring and using Cygwin is super easy. You can download the 32 or b4 bit versions of Cygwin at the following location. I am going to go over the installation and customization so that you can easily compile and build your C and C++ applications.

Installation Wizard

Once you have downloaded the relevant executable for your OS, run your executable. You should be presented with an installation wizard. Just follow the installation wizard. I used the default settings for the installation. I didn’t change anything and I suggest that you don’t either unless there is a specific reason to. All the paths and command line information presented below assumes the default information.

Note: When you are presented with the following screen on the installation wizard, ignore selecting any package and just press the Next > button. We will be using command prompt to get the necessary gcc and g++ packages.

Cygwin Installation Wizard Select Packages

Continue with the installation wizard and let the dependency download commence. Depending on your download speeds it may take some time to download all the necessary dependencies.

Package Installation

Now one of the very most important components for getting a compiler working outside of using an IDE like Visual Studio is making sure that you have the necessary packages. Open Command Prompt and enter the following in the command line:

setup-x86_64.exe -q -P wget -P gcc-g++ -P make -P diffutils -P libmpfr-devel -P libgmp-devel -P libmpc-devel

Note: The location of the executable was placed in my Download folder and the command was executed from that directory after I navigated to it.

After you have executed the command, the Cygwin setup should relaunch and it should proceed with the download and installation of the packages that were listed in the command line.

Verification

That is it 🙂

The compiler is installed and you can verify this by launching the Cygwin Terminal and entering in the command:

gcc --version

or

g++ --version

You should see the following displayed on the terminal. The versions of the compilers may be different depending when you install Cygwin and/or if you manually update to an even later version of the compiler (this has not been done here).

Cygwin Terminal Compi;er Versions

To test the compiler out (I’ll be testing the C++ compiler here) we can create a very simple C++ application and use the g++ compiler. The very first C++ program that I ever wrote was a simple Hello World program. What better way to test the installation of the g++ compiler than to use that simple C++ program. Below is the sample code in case you want to start learning C++ and/or you just want to quickly test your compiler but not actually write any code yourself.

#include <iostream>

using namespace std;

int main() {
    cout << "Hello World!" << endl;
    cin.get();
    return 0;
}

Save the above code as HelloWorld.cpp or use your own piece of C++ code and place it in the location of your Cygwin home user directory. By default it should be under C drive, ie. C:\cygwin64\home\<username>.

To compile the C++ code all you need to do is run the following command in the Cygwin Terminal:

g++ HelloWorld.cpp -o HelloWorld

What this will do is create an executable that is called “HelloWorld.exe” that you can then run from either the terminal or straight from the Windows Explorer. If you run the above piece of code in the Cygwin Terminal then the output should match exactly what is shown below; note that the program is waiting on user input before it terminates.

Cpp HelloWorld Terminal Compile And Run

There you go. You now have a Linux like C and C++ compiler installed on Windows and you do not need to have an IDE to compile and build your C or C++ projects. Hopefully this little guide and my desire to go back to C/C++ has fueled your own fire. Enjoy!

Software Development: Crunch

Nearly everyone in their working life will experience at some point a very tight deadline, significantly increased pressure to complete a specific task, and/or an insanely amount of extra hours that are expected of you to do. In the software industry (could also be used in other industries not too sure) this is referred to as “crunch“. There are many articles out there about crunch, especially in the video game industry. It is a time where you rarely see your family and friends, you eat and drink way too much junk food, your regular exercise regime is thrown completely out the window, and you may even dream about the code you had written (and not in a good way).

Currently during my software engineering career I have only ever experienced this crunch period twice. I wouldn’t consider the first time really crunch though. I did have to work towards a really tight deadline, longer hours, but it was only for a very short time. The second crunch I experienced was recently and it was for a longer period with an insanely tight deadline, a significant amount of work, and very long hours both during the normal work week and weekend. Personally I think crunch every so often, but not too frequently is a good thing. A little stress and hard work can be beneficial. In saying that though, working in an environment where you are in crunch mode every couple of weeks is probably not great for your well-being and highlights a potential problem with the operations of your organisation.

During my crunch I had to unfortunately stop attending my BJJ classes, working on my side projects, playing video games and even going out with friends and having a couple of beers. After my crunch period ended, I was exhausted but I made a commitment to myself to go back to my BJJ classes and attend my usual social gatherings at the minimum. With the software engineers that I worked with during this crunch period, I asked them how did they cope with all the stress, what techniques they used to mitigate feeling like garbage, and do they have any tips or tricks to make crunch not feel like a massive drain? All of them essentially came back with the same or similar responses:

  1. Breathe and take everything one step at a time:
    • Don’t panic as panicking will only make things worse.
    • Rushing or not paying attention to what you are doing will only cause you to make more mistakes and then cause you to panic even more.
  2. Switch off after your day is done:
    • You most likely won’t work for 24 hours so when you are done for the day and have worked close to 20 hours, clock off.
    • Focus on something you enjoy and do not bring your work home with you.
    • Be with your family and/or friends, or enjoy what little sleep you can get.
  3. Communicate and do it early:
    • There is nothing worse than needing help and not asking for it, you will only then fall further behind, rush and make mistakes and/or panic.
    • Others may be able to help you solve the problem faster and you will less likely panic if you know that others are here to help.

Along with all of these handy little tips and tricks I remembered some of the useful information that was presented in “The Clean Coder: A Code of Conduct for Professional Programmers” Chapter 11 – Pressure. That chapter essentially had the same information as what my colleagues had said to me.

Come the next crunch (which I know will happen at some point in the future) I will be better prepared mentally and will ensure that when I do get some time to myself\ I spend it making sure my body gets the rest it deserves or spend it with the people I enjoy being around. Keep my mind and body sane and happy 🙂