If-then - Nested vs. blocks (Bash)

Uit De Vliegende Brigade
Versie door Jeroen Strompf (overleg | bijdragen) op 6 mrt 2023 om 21:04
(wijz) ← Oudere versie | Huidige versie (wijz) | Nieuwere versie → (wijz)
Naar navigatie springen Naar zoeken springen

I don't think this is a design pattern, but it's a small thing I've noticed over the years: When you need to check for multiple conditions, it's usually easier to do so in blocks of 'loosely coupled' statements, rather than in one 'tightly integrated' nested if-then statements: The latter is so much more work to understand and use.

The case that I use here, is about evaluating different ways that this routine gets its only argument: Against which website (within an Apache server) should it execute?

Nested statements

The promise of these nested statements is, that it is very efficient and somehow natural:

###############################################################################
# Initialisation
###############################################################################
#
# Welcome message
########################################
#
echo ""; echo ""; echo "### wp_sr_up.sh()..."


# 1. Process command line argument?
########################################
#
# * $0: Name of the script
# * $1: First argument, etc.
#
#
if
   #
   # Check if command line argument has been provided
   #
   [ "$1" ]
then
   #
   echo "   Command line argument has been provided: $1"
   #
   # Check command line argument
   ########################################
   #
   if
      [ -f "$1/wp-config.php" ]
   then
      #
      echo "   Command line argument seems to point to a valid WordPress site"
      path_local="$1"
   else
      echo "   File ${1}/wp-config.php not found. Exiting"
      exit
   fi
else
   #
   echo "   Executed without command line argument..."
   #
   # 2. Executed from the root of a site?
   ########################################
   #
   if
      [ -f "./wp-config.php" ]
   then 
      echo "   PWD seems to be the the root of a WordPress site"
      path_local="$1"
   else
      #
      echo "   Executed outside the root of a WordPress site..."
      #
      # 3. Global variable "$path" being used?
      ########################################
      #
      # Does "$path" have content?
      #
      echo "   Variable path: $path"
      #
      if
         [ "$path" ]
      then
         echo "   Variable 'path' contains value: $path"
         #
         # Check for wp-config.php
         #
         if
            [ -f "$path/wp-config.php" ]
         then
            #
            # $path seems valid. Ask user for confirmation
            #
            echo "   Path seems ok"
            read -p "   Continue (y/n)? " continue
            #
            if
               [ "$continue" = "y" ]
            then
               #
               path_local="$1"
               #
            else
               #
               echo "   Terminated by user"
               exit
               #
            fi
         else
            #
            echo "   Variable 'path' has a value, but doesn't seem to point to a valid WordPress site"
            echo "   Exiting."
            exit
            #      
         fi
      else
         #
         echo "   Variable path doesn't seem to contain any value"
         echo "   Exiting."
         exit
         #
      fi
   fi
fi

Hybrid

In stead of nested if-then-statements, it is now in three blocks, which some of them still contain a nested statement:

###############################################################################
# Argument
###############################################################################
#
# Reset path_local
########################################
#
path_local=""


# 1. Command line argument?
########################################
#
# * $0: Name of the script
# * $1: First argument, etc.
#
if
	[ "$1" ]
then
	#
	echo "	Command line argument provided: $1"
	#
	if
		[ -f "$1/wp-config.php" ]
	then
		#
		echo "   Command line argument seems to point to a valid WordPress site"
		path_local="$1"
	else
		echo "	File ${1}/wp-config.php not found. Exiting"
		exit
	fi
else
	#
	echo "	No command line argument provided"
	#
fi


# 2. PWD is a WordPress site?
########################################
#
if
	[[ ! "$path_local" ]] && [ -f "./wp-config.php" ]
then
	#
	echo "	PWD seems to be a WordPress site."
	#
	path_local="$1"
	#
else
	#
	echo "	PWD doesn't seem to be a WordPress site."
	#
fi	


# 3. Global variable "$path" being used?
########################################
#
if
	[[ ! "$path_local" ]] && [ "$path" ]
then
	#
	echo "	Global variable 'path' seems to have a value"
	#
	if
		[ -f "$path/wp-config.php" ]
	then
		#
		# $path seems valid. Ask user for confirmation
		#
		echo "	Path seems ok"
		read -p "	Continue (y/n)? " continue
		#
		if
			[ "$continue" = "y" ]
		then
			#
			path_local="$1"
			#
		else
			#
			echo "	Terminated by user"
			exit
			#
		fi
	else
		#
		echo "	Variable 'path' has a value, but doesn't seem to point to a valid WordPress site"
		echo "	Exiting."
		exit
		#		
	fi
else
	#
	echo "	Variable path doesn't seem to contain any value"
	echo "	Exiting."
	exit
	#
fi

Only blocks

Now without any nested if-then-statements (except for the third case, where user input is incorporated):

  • Not every case is tested (and reported about by using echo, but it's much easier to read and to maintain - I think that's way more important
  • To my surprise, this is only 82 lines of code, compaired to 104 for the first example (which also reported much more extensively)
  • BTW, I only now found some errors in the previous scripts.
###############################################################################
# Argument
###############################################################################
#
# Reset path_local
########################################
#
path_local=""


# 1. Command line argument?
########################################
#
# * $0: Name of the script
# * $1: First argument, etc.
#
if
   [ "$1" ] && [ -f "$1/wp-config.php" ]
then
   #
   echo "   Command line argument provided: $1"
   echo "   Command line argument seems to point to a valid WordPress site"
   path_local="$1"
   #
fi


# 2. PWD is a WordPress site?
########################################
#
if
   [[ ! "$path_local" ]] && [ -f "./wp-config.php" ]
then
   #
   echo "   PWD seems to be a WordPress site."
   path_local="$PWD"
   #
fi   


# 3. Global variable "$path" being used?
########################################
#
if
   [[ ! "$path_local" ]] && [ "$path" ] && [ -f "$path/wp-config.php" ]
then
   #
   echo "   Global variable 'path' seems to point to a WordPress site"
   read -p "   Continue (y/n)? " continue
   #
   if
      [ "$continue" = "y" ]
   then
      #
      path_local="$path"
      #
   else
      #
      echo "   Terminated by user"
      #
   fi
   #
fi


# Still no value? → Exit
########################################
#
if
   [[ ! "$path_local" ]]
then
   #
   echo "   No WordPress site found. Exiting"
   exit
   #
fi


# Got a value!
########################################
#
echo "   And the path is: $path_local"