Rob Kraft's Software Development Blog

Software Development Insights

Archive for August, 2015

Robert’s Rules of Coders: #5 Organize Your Code

Posted by robkraft on August 30, 2015

When you write programs that consist of many lines of code, where the threshold of “many lines” probably begins around fifty lines of code, you should consider organizing your code in ways that will make it easier for you to maintain it in the future.  Breaking the code into many functions is a good start, but when you have a lot of functions it can become difficult to manage and remember them.  At this point you should consider grouping related functions, and in most programming languages placing the groups of related functions into separate files.

The major benefit is that you, and other developers, can more easily find the code you are looking for when you want to examine or modify it.

You may consider placing all functions you use to generate and send emails into a single file that you name Email.Code.  You may move all of your functions for formatting strings into a file name StringFormatting.Code.  Organizing your code into separate logically grouped files provides the simple benefit of helping developers find the code to be worked on more quickly.  For example, if you are on vacation and I need to fix a bug related to emails in your code, I can find the bug more easily if the email code is in its own file than if all of the program code is in one single large file.

Having many separate files for your code also helps you track changes in the code when you are using a source code control system; which you should be doing.  For example, if I made a change several months ago to the Email.Code and I now realize that my change might have broken something, I can use my source code control system to review the changes made to Email.Code more easily than I can use it to review the changes to All.Code.

Business developers often use the technique of object oriented programming to help determine how to organize their code into separate files.  The programmer may put all the code related to customers in Customer.Code, and all of the code related to products in Products.Code.  Although placing code in separate files is not what object oriented code is really about, it is a natural side effect.  Large object oriented applications may use several files for a single “object”. Instead of just a single file for Customers, the code may be broken into several files such as CustomerProperties.Code, CustomerPersistence.Code, and CustomerBusinessRules.Code.  Once again the primary reason for multiple files is usually because programmers have learned that many small source code files are easier to develop with than a single large file of code.  Another benefit when there are multiple developers may be that each developer focuses on a different area of expertise and one developer focuses on …Persistence.Code files and another developer focuses on …BusinessRules.Code.

An additional approach to organizing code, and I choose the word additional because it could and should be used along with organizing code by object and function, is to group code in different layers of the application architecture together.  Many applications today consist of at least three layers:

  • a User Interface (UI) layer,
  • a business logic layer,
  • and a data persistence layer that stores data in files or databases.

It is very beneficial for developers to keep the code in these layers separate because it makes it easier for the developer to make some changes in the future.  On such change could be storing data in a different type of database.  Another could be replacing the desktop UI with a web page UI.

In object oriented development, developers following the SOLID principles, will implement the “Single Responsibility” principle which leads them to limiting each “class” to doing just one thing, hence the term “Single Responsibility”.  Although this does not necessarily dictate that a developer will only have one class per file, that is often the case and thus followers of the “Single Responsibility” pattern are likely to organize code into separate manageable files.

So instead of placing all of your code in a single file like this:

File1: AllMyCode.code

All Code in One File

All Code in One File

Break the code into separate files like this:

File1: UICode.code

Code In 1st File

Code In UICode.Code file

File2: ProductCode.code

Code In ProductCode.Code File

Code In ProductCode.Code File

File3: CustomerCode.code

Code in CustomerCode.Code File

Code in CustomerCode.Code File

File4: EmailCode.code

Code In EmailCode.Code File

Code In EmailCode.Code File

Go to Robert’s Rules of Coders for more.

Advertisements

Posted in Code Design, CodeProject, Coding, Robert's Rules of Coders | Leave a Comment »

Robert’s Rules of Coders: #4 Make Functions Short

Posted by robkraft on August 18, 2015

Functions are easier to understand and thus easier to maintain when they are short.  You can often make functions shorter by finding patterns in a large function and extracting those lines of code comprising the pattern into a separate function and calling the separate function as shown below.

One Long Function

One Long Function

One Short Function With The Same Results

One Short Function With The Same Results

Note: The FormatForOutput function is not shown because I believe you can figure out what it does.

But even when you have a long function with no lines of code that are duplicated, you can often make the code more readable and easier to maintain by separating the code into functions.  Consider this example:

One Long Function

One Long Function

Long Function Broken Into Short Functions

Long Function Broken Into Short Functions

Note: The 4 new functions are not shown because I believe you can figure out what they do.

Most developers will be able to understand the 2nd example better than the first.  But there is another big benefit that applies in a lot of languages.  Let’s assume that an error occurs with a message of “Object variable is null”.  In the first example, the error message might show a call stack that says our program named Program1 called the method MainCodeBlock and this error occurred within MainCodeBlock.

Call Stack from First Example:

  • Program1
    • MainCodeBlock

But which line of code within MainCodeBlock?  We don’t know and it could have been caused by many of the lines.  However, if the same error occurs in the second example, our call stack would look like:

Call Stack from Second Example:

  • Program1
    • MainCodeBlock
      • SavePriceToDatabase

In the second example, we have narrowed down the problem to the SavePriceToDatabase method and have only a few lines of code to consider as the source of the error.  This is another benefit of smaller functions.

Finally, for those of you that write unit tests as most good programmers should, you have functions neatly wrapped up and ready to be called by those unit tests.

In summary, short functions provide these benefits:

  • They organize your code, making it easier to understand and maintain.
  • They make it easier to pinpoint bugs when you have a call stack.
  • They make it easier for you to write unit tests for your code.

Go to Robert’s Rules of Coders for more.

Posted in Code Design, CodeProject, Coding, Robert's Rules of Coders | Leave a Comment »

Robert’s Rules of Coders: #3 Use Good, Meaningful Names

Posted by robkraft on August 6, 2015

Code is much easier for humans to read when the variable and function names reflect what they mean and do.  In ancient times, like the 1960s, some programming languages did not support long variable names, but today most every language supports long names with no penalties.  Although some exceptions may be tolerated for very common usages such as the variables “I”, “j”, and “k” for loops, you should strive to use meaningful names in all cases.  Would anyone honestly say that the first block of code below is easier to understand than the second?

Code with and without good names

Code with and without good names

Good, meaningful names not only make your code more readable, but they may also remove the need for you to add comments or documentation to the code.

When we first began writing javascript in the 1990s we used short variable names because we wanted to reduce the size of the files to make them faster.  Today, you should probably not do this because the data is compressed by default by technologies like gzip, and Internet speeds are faster, and if you are writing enough code that the size of your javascript is a factor you should be using a minifier tool to make the javascript smaller for you.

Aside from long names, what makes a variable or function name good?

  •  Good names reflect the value stored in the variable or explain what the function does. “Counter1” is better than “c”, but “ActionCounter” is even better. Giving variables relevant names reduces the time it takes people in the future looking at the code to figure out what it does. And that includes the future you. This applies to function names also. A function named “UpdateActivityCount” is better than “CountUpdater”.
  • Try not to use negative logic in variable and function names. It takes our brains a little longer to deduce the meaning of negative logic statements.
    • IsValid is usually a better name than IsNotValid
    • DoesValueExceedMaximum is usually better than DoesValueNotExceedMaximum
  • Follow the conventions of the language you are coding in. If the language uses CamelCase, you should use CamelCase. If the language uses Hungarian Notation (txtFirstName, intItemCount), you should use Hungarian notation. If the language uses all upper case for the names of CONSTANTS, you should use all upper case for CONSTANTS too.
  • Don’t reuse variable names for different purposes.
Example of Reusing a Variable

Example of Reusing a Variable

  • The function name should describe what it does not how it does it.  This allows you to change how the code in the function works without needing to change the function name. This helps the function remain a black box.
    • Name the function GetAllCustomers, not CallDatabaseUsingADOtoGetDataFromCMCUSTTable.
  • Avoid names that might match keywords. Naming a variable “Name” or “Date” might compile safely at first, but it might fail after an update to the language is installed, or if you include a new library in the project. Also, it may not be obvious to other developers that the variable name is one that you created instead of one that is built in.
  • Follow a consistent pattern
    • If your Foo object has a Retrieve method to get data from the database, then your Bar object should also have a Retrieve method to get data from the database, not a Get method. Using the same method and property names across objects when the methods serve the same functions reduces the learning curve for new developers.
    • You should also strive to use consistent noun and verb pairings.  Naming two functions CalculateLastSaturday and CalculateLastSunday is usually easier for programmers to remember than having one function named CalculateLastSaturday and the other named FigureOutFinalSunday.

Finally, remember to rename your variables if the meaning of the value they store changes and rename your functions if the things the function does changes.  We are writing code for humans, not for computers.

Are there any more good rules that should be added to this list?

Posted in Code Design, CodeProject, Coding, Robert's Rules of Coders | Leave a Comment »

Robert’s Rules of Coders: #2 Avoid Global Variables

Posted by robkraft on August 2, 2015

Global variables are variables that can be accessed from anywhere in the program.  It is appropriate to use a global variable when you have a value that is a constant and thus won’t change as the program runs, but it is rarely appropriate to use global variables for values that change while the program is running.

Functions should usually return the same output when given the same inputs.  Global variables in functions can cause the function to return different values, making the function less reliable and more difficult to write unit tests for.

A Bad Program With Global Variables

A Bad Program With Global Variables

In the block of code above, you can see that the value returned from CalculatePrice() is not predictable.  In the first case it returned 11.00, but in the second case it returned 10.50 for the same inputs.  Here is a second version of the program:

Same Program Without Global Variables

Same Program Without Global Variables

The second version of the program has the following advantages:

  • The programmer can see all the factors that affect the TotalPrice.  None are hidden.
  • The programmer can write unit tests against the CalculatePrice() function more easily.
    • Assert.That( CalculatePrice(4, $2.5, 10%) = 11.00)

The problems with using global variables include the following:

  • Global variables can be modified from anywhere in the program, making the output of functions using them less predictable
  • Rules that you code in one place about setting the value of a global variable may not be adhered to in other places. For example one block of code may do this:
Setting Global From Spot 1

Setting Global From Spot 1

But another block of code in the program may do this:

CodeArt2-4

Setting Global from Spot 2

  • A function or component that uses global variables becomes “tightly coupled” to the other components that use the global variable.  This entanglement increases programmatic complexity which means the program is probably more difficult to maintain and enhance, and also that it is difficult to replace one component of the program without affecting others.
  • In multithreaded programs, global variables may not be thread-safe.
  • In some languages, global variables make it difficult to add new components to an existing program because the new component may contain its own global variables with the same name.

When you have an object that you think should be global so that it can be used everywhere, you should probably use Dependency Injection.  Don’t be deceived by the Singleton pattern for a global variable replacement because that often becomes just a more complicated version of a global variable.

Posted in Code Design, CodeProject, Coding, Robert's Rules of Coders | Leave a Comment »

Robert’s Rules of Coders: #1 Write Subroutines Profusely

Posted by robkraft on August 1, 2015

Most programming languages support the concept of a subroutine.  A subroutine is a block of code that your current code calls (aka executes) to run some more code.  Subroutines are called by many different names, with some of the most common being ‘function’, ‘method’, or ‘procedure’.

Subroutines serve two primary purposes:

  1. They allow you to easily reuse some of your code
  2. They organize your code, making it easier to read and maintain.

A program without subroutines

A Program Without Subroutines

A Program Without Subroutines

A program with subroutines

A Program With Subroutines

A Program With Subroutines

The advantages of the program that uses subroutines include:

  • The code is easier for another person to read, and that other person could be the future you.
  • Code that is re-used provides these benefits
    • You spend less time writing code because you can use code that already exists, the subroutine that you wrote.
    • The subroutine is already proven to work when used the first time.  You won’t have to spend time fixing logic errors and typos each subsequent time you want to do the same things.
    • If you discover a bug in the subroutine you can fix it in the subroutine which fixes it for all places from which it is called. In the first program above, if you found a bug formatting Item1PriceOut the same bug would probably also exist in formatting Item2PriceOut and need to be fixed there too.
    • If you decide something should be changed, such as using “<strong>” instead of “<b>” when formatting your string you can make the change once instead of making it in several places.
    • You can optimize the code later. Perhaps you later learn that you can call ConvertToDollars() and the formatting to two decimal places will be handled for you. You can make the change in the subroutine instead of making the change several times as you would have to do in the first program above.
Easily Change a Subroutine

Easily Change a Subroutine

  • The subroutine is more likely to be testable from an automated test.  Many languages allow you to write “unit tests” that can be run regularly to insure your code keeps working as intended even after you make changes to it over time.  It is easier to unit test code isolated in a subroutine than it is to unit test code that is just part of a larger code block.
    • Example Unit Tests:
      • Assert.That( FormatForOutput(7) = “$7.00”)
      • Assert.That( FormatForOutput(7.1) = “$7.10”)
      • Assert.That( FormatForOutput(555) = “<b>$555.00</b>”)
  • The size of the code is usually smaller when using functions, taking less disk space.
  • The size of a compiled version of the program is probably smaller, taking less disk space.
  • The size of the program in memory is probably smaller, using less RAM.
  • The memory allocated to variables is more likely to be re-used which therefore requires less RAM.

Use Subroutines Profusely

I recommend using subroutines when you see that you have two or more lines of code that are the same over and over in the program.  One thing that makes a programmer a good programmer is the ability to see patterns.  So even though these lines of code are not the same, a good programmer will see that there is a pattern and extract that pattern into a subroutine:

Can You See A Pattern?

Can You See A Pattern?

Becomes

Pattern Implemented in a Subroutine

Pattern Implemented in a Subroutine

In this case, the second program has more lines of code, but if you need to modify Item3PriceOut and Item4PriceOut the program with subroutines will become the shorter program.  And it will be easier to maintain.

Use Subroutines to Hide Complexity and Third Party Dependencies

Use subroutines for anything that might change and is used more than once, especially third party dependencies.  For example, if you use a third party tool called 123Logger in your code like this:

3rd Party Code Inline

3rd Party Code Inline

Replace it with code like the following because if you ever want to change to a different logger than 123Logger, you will only need to change your code in one place.  You are writing your code so that it is not as dependent on how the third party logger software needs to be called.

3rd Party Code in a Subroutine

3rd Party Code in a Subroutine

When you decide to use XYZLogger instead of 123Logger, you can change your code to look like this:

Using Different 3rd Party Code

Using Different 3rd Party Code

There are even better ways to handle third party dependencies like this for larger applications, but this approach is a good start.

Posted in Code Design, CodeProject, Coding, Robert's Rules of Coders | 1 Comment »