Устранение дублирования в функции сравнения версий


Исходный код

function CheckVersion($version1, $version2)
{
	$arr1 = explode(".",$version1);
	$arr2 = explode(".",$version2);
	if (intval($arr2[0])>intval($arr1[0])) return false;
	elseif (intval($arr2[0])<intval($arr1[0])) return true;
	else
	{
		if (intval($arr2[1])>intval($arr1[1])) return false;
		elseif (intval($arr2[1])<intval($arr1[1])) return true;
		else
		{
			if (intval($arr2[2])>intval($arr1[2])) return false;
			elseif (intval($arr2[2])<intval($arr1[2])) return true;
			else return true;
		}
	}
}

Что не так в исходном коде

Нет смысла самостоятельно реализовывать алгоритмы, которые уже реализованы в стандартных библиотеках. В PHP для сравнения версий уже существует функция version_compare. Подход, когда вместо библиотечных функций применяются собственные многословные реализации, традиционно называется велосипедом.

Это решение максимально тривиальное, тут не о чем рассуждать. Допустим, оно меня по какой-то причине не устраивает и мне позарез нужна собственная реализация сравнения версий.

Первое, что я захочу сделать — расширить контракт функции: мне нужно, чтобы она возращала на два варианта результата, а три. Это даст больший простор для её применения, а если очень понадобится именно исходный контракт — всегда можно сделать адаптер.

Второе — я уберу внутрь цикла дублирующийся код сравнения компонентов версии. То, что дублируется — это реализация алгоритма сравнения компонентов версии.

Вариант рефакторинга

function CompareVersion($version1, $version2)
{
	$version1_arr = explode(".", $version1);
	$version2_arr = explode(".", $version2);
	$version_length = max(count($version1_arr), count($version2_arr));
	for ($i = 0; $i < $version_length; $i++) {
		$version1_part = intval($version1_arr[$i]);
		$version2_part = intval($version2_arr[$i]);
		if ($version1_part < $version2_part) {
			return -1;
		}
		if ($version1_part > $version2_part) {
			return 1;
		}
	}
	return 0;
}

Теория