Attach to Process

Thoughts and Notes on Software Development

Updated: 4/26/2021

Coney complained to me this morning that the YouTube videos on my latest music log entry were getting cut off when viewed from her phone. I've known about this issue for awhile, but didn't really try to find a solution for it. Well, today I did and it turns out to be really easy.

The issue stems from the fact that I have to use iframes to embed videos on write.as sites. To make the YouTube videos I embed on write.as sites responsive, I simply followed the instructions from this Responsive Youtube Embed post. Specifically, these are the changes I added to my journal.

Read more...

If it ain't broke, don't fix it.

The most important software development principle that everyone should be following is “If it ain't broke, don't fix it.” I know, I know, it's not really a principle coming from the realm of computer science or software development, but it should be. Adhering to this sage life advice is just as beneficial when writing code, as it is in everyday life. Forget about trying to master the five SOLID design principles if you can't even follow this one.

If you're constantly trying to fix stuff that wasn't broken to begin with, you're in for a lot of headaches in your software development career. Not to mention, headaches for other developers in your team. If you find a piece of code that is working, that is not causing bugs, that is not causing performance issues, you best leave that piece of code alone.

Tags: #SoftwareDesignPrinciples

Discuss... or leave a comment below.

I was reading this article about Xamarin and Swift when I noticed this useful piece of information at the end:

If Swift continues to take the iOS world by storm, more such documentation may be needed. The February 2020 TIOBE Index, which measures programming language popularity, shows Swift at No. 10, having moved up a full 10 positions from the February 2019 ranking, making it the biggest mover in the top 20. C#, used for Xamarin coding, is at No. 5, moving up from No. 7 last year.

Interesting. That bit of info led me to this, the TIOBE Index.

The TIOBE Programming Community index is an indicator of the popularity of programming languages. The index is updated once a month. The ratings are based on the number of skilled engineers world-wide, courses and third party vendors. Popular search engines such as Google, Bing, Yahoo!, Wikipedia, Amazon, YouTube and Baidu are used to calculate the ratings. It is important to note that the TIOBE index is not about the best programming language or the language in which most lines of code have been written.

The index can be used to check whether your programming skills are still up to date or to make a strategic decision about what programming language should be adopted when starting to build a new software system.

I see this as a very useful tool for software developers, not just in figuring out what programming language to use when building a new application, but also in figuring out what programming language to learn or focus on to improve your career as a software developer.

I'm glad to see C# making its way up on the list. I thought Python would be on top, but I guess Java is still too popular nowadays. Also, I keep reading about Rust in the dev blogs/websites that I follow. I wonder when it will break into the Top 20 list? Either way, I think this index is a good list to keep our eyes on as software developers.

Tags: #Bookmarks #ProgrammingLanguages

Discuss... or leave a comment below.

This is a great resource for anyone who wants to get started with C# and .NET Core.

Link: Hundreds of practical ASP.NET Core samples to learn the fundamentals

Tags: #Bookmarks #AspDotNet #DotNet #DotNetCore

Discuss... or leave a comment below.

In this post, I'll share my thoughts regarding the use of the Single Responsibility Principle based on my experiences with it.

The Single Responsibility Principle is one of the five design principles listed in SOLID. Gary McLean Hall in his book “Adaptive Code via C#” says,

“The single responsibility principle instructs developers to write code that has one and only one reason to change. If a class has more than one reason to change, it has more than one responsibility. Classes with more than a single responsibility should be broken down into smaller classes, each of which should have only one responsibility and reason to change.”

It is my favorite principle out of the five because of two reasons:

1. Easy to Implement

First, it is very easy to implement. You don't have to be an experienced software developer to start implementing the single responsibility principle in your code. All you need to keep in mind when writing code for a new class or sometimes even a method is, this block of code should be responsible for only one thing.

Are you writing code for a class to parse text files? Then make sure all the code in that class is oriented towards parsing text files. Are you writing code for a class that is supposed to send email notifications? Then keep the code focused on sending email notifications.

2. Better Code

Second reason is that it will always make your code better. Better in the sense that it helps decouples your classes/methods, which reduces the potential for bugs when refactoring code. This in turn also makes your code easier to test. In my experience, I have never seen code that was made worse by implementing the single responsibility principle.

Drawbacks?

The only argument or drawback I've heard to the use of this principle, is the possibility of increased maintenance of the code. Since each class is responsible for doing only one thing, you could end up with a lot more classes, methods, files and projects in your solution. Still, in my opinion, that is preferable if it means I have stable code that is less prone to bugs, than to have code that is low maintenance but is susceptible to bugs.

There is also the chance that a developer will try to implement this principle on a very simple app that doesn't need to change after it's been written. In this case, trying to implement the single responsibility principle will probably take more time and add complexity to the code. (I haven't exactly ran into a situation like this with this principle, but I think that's a possibility.) Sometimes you will have to pick and choose where and when to implement this principle, and that can only come with experience.

Example

Let me go through an example where I think the use of the single responsibility principle would help.

Say you have a business rule that needs to be implemented for various products. Say that Product A, B and C all use this business rule. One thing I've seen in my experience is that if the business rule logic is similar between Products A, B or C, some developers will opt to create just one class to implement the business rule for all products. Again the argument here is that since the business logic is the same, it is easier to maintain just one class for the specific business rule. Okay, fair enough. As long as the business rule doesn't have to change between any of the products, having one class/method for the business rule is acceptable. It is in violation of the single responsibility principle, but if the business rules won't ever change, then it is an acceptable implementation.

But what if the business rules does change for one product, say for Product C? Now you'll have to modify the one class that all products use, to accommodate changes for just one product. What this means is that while working on the new changes, you have an increased chance of introducing bugs to the rest of the products. This also means that any changes to that business rule for any one product, means you have to perform testing for all other products affected by the changes. That is extra work that could have been avoided by following the single responsibility principle.

Now what if you have to add new products that will also have the same business rule, except the new products have slightly different business rule logic in them? Will you modify the existing class to accommodate changes for the new products? If so, you'll run into the same issue above. Adding new products will almost feel like a way to introduce bugs to your code. You can avoid that by following the single responsibility principle.

With the use of the single responsibility principle, each product would have one class that implements a specific business rule. Any changes to the business rules for one product, will not affect the other products. Which means going forward, you only need to worry about testing the changes for the products that changed or the products that were added. Everything else should keep working the same way they've been working before. Stress free coding with minimal chances of introducing bugs, just the way I like it.

Tags: #CSharp #DotNet #SolidPrinciples #SoftwareDesignPrinciples

Discuss... or leave a comment below.

Update 4/23/2021: The write.as team has introduced some rate-limiting features on their API to combat spam bots. That stopped this Glitch app and my other Blazor WASM apps from working.

I created a Glitch App that displays the most viewed posts on my online journal. I embedded it on my About page. Just to show how easy it is to embed a Glitch app into a Write.as post, I embedded it at the bottom of this post too. For more information on embedding Glitch apps into posts on Write.as, look here.

Read more...

Update 4/23/2021: The write.as team has introduced some rate-limiting features on their API to combat spam bots. That stopped this Glitch app and my other Blazor WASM apps from working.

Took me a couple of days, but I got my journal search page up and running. That was a great learning experience.

If you want to remix my search app, you can find it here. If you want to remix the original Write.as Search app, you can find it here.

Prior to creating a Write.as blog, I've never even heard of Glitch. Below is a list of notes and references I've made while trying to get my search page working.

Read more...

The most convenient way it seems to get .NET Core 3.0 installed on a Windows PC, is to download the free Microsoft Visual Studio 2019 Community edition. Installing Visual Studio 2019 will also install .NET Core 3.0 and after the installation is done, you can start playing around with it.

If you want to download the SDK or just the runtime separately, you can find them here.

To check if you already have .NET Core 3.0 installed, you can pull up a Command Prompt and run the dotnet --version command.

Lastly, if you're trying to learn ASP.NET Core like I am, this recommended learning path seems to be a good starting point.

Tags: #CSharp #DotNetCore

Discuss... or leave a comment below.

For the past month or so, I have noticed that I've been pointing out the need to do case-insensitive string comparisons in the code reviews that I've done. In light of that, I thought now would be a good time to do a refresher on string comparisons in C#.

Using the == operator

Doing string comparisons in C# is easy, and the easiest way to do it, is with the == operator.

public static void Main()
{
   string userName1 = "dino";
   string userName2 = "dino";
   bool areStringsEqual = userName1 == userName2;
   Console.WriteLine(areStringsEqual.ToString());
}

Result: True

The main drawback to this approach is that it will only do a case-sensitive comparison. So, any typo like in the sample code below, will not work.

public static void Main()
{
   string userName1 = "dino";
   string userName2 = "dinO";
   bool areStringsEqual = userName1 == userName2;
   Console.WriteLine(areStringsEqual.ToString());
}

Result: False

So, let's look at another approach to comparing strings...

Using ToUpper() or ToLower()

For quick case-insensitive string comparisons, you can call ToUpper() or ToLower() on your strings before doing the comparison using the == operator.

public static void Main()
{
   string userName1 = "dino";
   string userName2 = "DiNo";
   bool areStringsEqual = userName1.ToUpper() == userName2.ToUpper();
   Console.WriteLine(areStringsEqual.ToString());
}

Result: True

I don't see much drawbacks to using this approach, except if one of your strings is null, in which case you'll then have a NullReferenceException on your hands, like in the sample code below.

public static void Main()
{
   string userName1 = "dino";
   string userName2 = null;
   bool areStringsEqual = userName1.ToUpper() == userName2.ToUpper();
   Console.WriteLine(areStringsEqual.ToString());
}

Result: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object.

Note: The exception message above might look weird, but that is because I am running the sample code on TryDotNet.

So, there is an extra step of making sure the strings are not null before you call one of its methods, like in the sample code below.

public static void Main()
{
   string userName1 = "dino";
   string userName2 = null;
   bool areStringsEqual = userName1 != null && userName2 != null && (userName1.ToUpper() == userName2.ToUpper());
   Console.WriteLine(areStringsEqual.ToString());
}

Result: False

The sample code above is still very much usable code, but having to do the null checks all the time can be tiring, which leads me to another way of doing string comparisons...

Using String.Compare

Using the static Compare method from the String class allows you to easily do a case-sensitive or case-insensitive string comparison using the ignoreCase parameter, like in the sample codes below.

Case-insensitive comparison:

public static void Main()
{
   string userName1 = "dino";
   string userName2 = "DiNo";
   bool areStringsEqual = String.Compare(userName1, userName2, ignoreCase: true) == 0;
   Console.WriteLine(areStringsEqual.ToString());
}

Result: True

Case-sensitive comparison:

public static void Main()
{
   string userName1 = "dino";
   string userName2 = "DiNo";
   bool areStringsEqual = String.Compare(userName1, userName2, ignoreCase: false) == 0;
   Console.WriteLine(areStringsEqual.ToString());
}

Result: False

The beauty of using the Compare method is that I don't even have to do null checks. So, taking the sample code above where I had to do null checks, and replacing it with a call to String.Compare, results in the much cleaner sample code below.

public static void Main()
{
   string userName1 = "dino";
   string userName2 = null;
   bool areStringsEqual = String.Compare(userName1, userName2, ignoreCase: true) == 0;
   Console.WriteLine(areStringsEqual.ToString());
}

Result: False

The only drawback to this approach is that it might be harder to read the first time around, because the String.Compare method returns an int, instead of a boolean value.

Normally when comparing strings, we are asking the question, are the strings equal? True or False? So, we are expecting a boolean value back. With the use of String.Compare method, you must compare the results to 0 to determine if the strings are equal. It might take a while to get used to, but the fact that you can throw any string object at this method and not worry about null checks and typos, to me that makes it the superior approach to string comparisons.

Which One Do I Use the Most?

When developing prototype applications or generally when I'm just testing something, I am fine with using the ToUpper() or ToLower() approach. When I'm guaranteed that none of the strings will be null, I would use the ToUpper() or ToLower() approach. Any other scenario, I prefer to use the String.Compare method.

Tags: #CSharp #DotNet

Discuss... or leave a comment below.

What is the best way to prove that your bug fix works? Well, you test it. How do you make sure your bug fix keeps working years into the future? You write a test for it.

Specifically, you want to write a test that can reproduce the bug. Only once you've been able to do this, do you actually try to fix the bug. There are several of benefits for using this approach to fixing bugs:

  • First, you don't have to manually go through the steps to reproduce the bug just to see if your fix works. Sure, you need to do a manual test to confirm that it works, but ideally you do this after you're done coding most of the changes. Having to do a manual test every single time you make a small code change will consume a lot of your time. Time that is better spent writing code and fixing more bugs.
  • Second, when working on another bug fix in the same class or in the same part of the application as a previous bug fix, an existing test will let you know if your new fix breaks an existing bug fix. Actually, this benefit is not restricted to just “previous bug fixes”. If you have tests, that cover the behavior of your whole application, then it is easier to verify if your new code changes break existing functionality.
  • Third, tests can be another way of documenting the behavior of an application. If you have a test that is named CustomerManager_Cannot_Save_Customer_Without_DriversLicenseNumber, that immediately tells me one of the requirements needed when saving Customer data. It also tells me what class or service is used to save Customer data. If I was a new developer and I was trying to learn how the system saves a Customer record, this test is a gateway to learning about that process. Having new developers go through tests is actually a great way to have them learn a new application/system.

Depending on the application or system you are working, writing tests might not be easy or might take too much time. If so, then that is a hint that the application or system you are working on might be so tightly coupled, that you cannot write a small “test” to test a specific part of the code. You should look into decoupling classes and making their methods smaller and modular, to make it easier to test various parts of the application. If you want to learn more about making your code easier to test, I suggest learning about SOLID Principles and looking into Test-Driven Development.

When I started out working professionally as a software developer, I actually didn't write any tests. I would just write code and test my changes manually. Nowadays, I feel uncomfortable about any code changes that I don't have tests for.

Tags: #Tests

Discuss... or leave a comment below.

Enter your email to subscribe to updates.