Вопрос
Что лучше использовать в PHP, 2D массив или класс?Я привел пример того, что я имею в виду под этим.
// Using a class
class someClass
{
public $name;
public $height;
public $weight;
function __construct($name, $height, $weight)
{
$this -> name = $name;
$this -> height = $height;
$this -> weight = $weight;
}
}
$classArray[1] = new someClass('Bob', 10, 20);
$classArray[2] = new someClass('Fred', 15, 10);
$classArray[3] = new someClass('Ned', 25, 30);
// Using a 2D array
$normalArray[1]['name'] = 'Bob';
$normalArray[1]['height'] = 10;
$normalArray[1]['weight'] = 20;
$normalArray[2]['name'] = 'Fred';
$normalArray[2]['height'] = 15;
$normalArray[2]['weight'] = 10;
$normalArray[3]['name'] = 'Ned';
$normalArray[3]['height'] = 25;
$normalArray[3]['weight'] = 30;
Предполагая, что кто-то не выйдет и не покажет, что занятия проходят слишком медленно, похоже, что класс выигрывает.
Я понятия не имею, с каким ответом мне следует согласиться, я только что проголосовал за все из них.
И теперь я написал две почти идентичные страницы, одну с использованием 2D-массива (написанную до публикации этого вопроса), а теперь еще одну с использованием класса, и я должен сказать, что класс создает гораздо более приятный код.Я понятия не имею, сколько накладных расходов будет сгенерировано, но я сомневаюсь, что это сравнится с улучшением самого кода.
Спасибо вам за то, что помогли сделать меня лучшим программистом.
Решение
"Класс", который вы создали выше, - это то, что большинство людей использовали бы в структура для других языков.Я не уверен, каковы последствия для производительности в PHP, хотя я подозреваю, что создание экземпляров объектов здесь, вероятно, обходится дороже, хотя бы немного.
При этом, на мой взгляд, если стоимость относительно низкая, управлять объектами немного проще.
Я говорю только следующее, основываясь на названии и вашем вопросе, но:Имейте в виду, что классы также предоставляют преимущество методов и контроля доступа.Итак, если вы хотите убедиться, что люди не меняют веса на отрицательные числа, вы могли бы сделать weight
укажите поле private и предоставьте некоторые методы доступа, такие как getWeight()
и setWeight()
.Внутри setWeight()
, вы могли бы выполнить некоторую проверку значения, например, так:
public function setWeight($weight)
{
if($weight >= 0)
{
$this->weight = $weight;
}
else
{
// Handle this scenario however you like
}
}
Другие советы
Это зависит от того, что именно вы подразумеваете под "лучше".Я бы выбрал объектно-ориентированный способ (с использованием классов), потому что я считаю, что это делает код чище (по крайней мере, на мой взгляд).Однако я не уверен, какими могут быть штрафы за скорость для этого варианта.
Как правило, я следую этому правилу:
1) Сделайте это классом, если несколько частей вашего приложения используют структуру данных.
2) Сделайте его 2D-массивом, если вы используете его для быстрой обработки данных в одной части вашего приложения.
В основном я думаю о скорости, для чего-то более сложного, чем то, что у меня есть здесь, я бы, вероятно, выбрал классы, но вопрос в том, какова стоимость класса?
Казалось бы, это преждевременная оптимизация.Ваше приложение в любом случае не пострадает от снижения производительности в реальном мире, но использование класса позволяет вам использовать методы получения и установки и, как правило, будет лучше для инкапсуляции кода и повторного использования кода.
Из-за массивов вы несете затраты на более сложный для чтения и обслуживания код, вы не можете так же легко выполнять модульное тестирование кода, а при хорошей структуре классов другим разработчикам должно быть легче понять, нужно ли им браться за это.
И когда позже вам нужно будет добавить другие методы для управления ими, у вас не будет архитектуры для расширения.
Класс, который у вас есть, не является реальным классом в терминах OO - он просто был сконструирован так, чтобы занимать пространство переменных экземпляра.
Тем не менее, вероятно, нет большой проблемы со скоростью - это просто стиль в вашем примере.
Интересный момент заключается в том, что если вы считаете объект реальным классом "person" и подумаете о других атрибутах и действиях, которые вы можете потребовать от класса person, то вы заметите не только производительность стиля написания кода, но и быстродействие.
Если ваш код использует множество функций, которые работают с этими атрибутами (name / height / weight), то использование class может быть хорошим вариантом.
Тейфион, если вы используете классы как простую замену массивам, вы далеки от ООП.Суть ООП заключается в том, что объекты обладают знаниями и ответственностью, действительно могут что-то делать и сотрудничать с другими классами.Ваши объекты обладают только знаниями и не могут делать ничего другого, кроме как просто существовать, однако они кажутся хорошими кандидатами для поставщиков сохраняемости (объекты, которые знают, как сохранять / извлекать себя в / из базы данных).
Не беспокойтесь и о производительности.Объекты в PHP быстры и легковесны, а производительность в целом сильно переоценивается.Дешевле сэкономить ваше время программиста, используя правильный подход, чем экономить микросекунды в вашей программе с помощью какого-то непонятного, трудно отлаживаемого и исправляемого фрагмента кода.
Большинство тестов, в которых используются массивы по сравнению с классами, тестируют только их создание.Как только вы действительно начнете что-то с ними делать.
Я был "пуристом", который использовал только массивы, потому что производительность была намного лучше.Я написал следующий код, чтобы оправдать перед самим собой дополнительные хлопоты, связанные с неиспользованием классов (хотя они проще для программиста)
Скажем так, я был ОЧЕНЬ удивлен результатами!
<?php
$rx = "";
$rt = "";
$rf = "";
$ta = 0; // total array time
$tc = 0; // total class time
// flip these to test different attributes
$test_globals = true;
$test_functions = true;
$test_assignments = true;
$test_reads = true;
// define class
class TestObject
{
public $a;
public $b;
public $c;
public $d;
public $e;
public $f;
public function __construct($a,$b,$c,$d,$e,$f)
{
$this->a = $a;
$this->b = $b;
$this->c = $c;
$this->d = $d;
$this->e = $e;
$this->f = $f;
}
public function setAtoB()
{
$this->a = $this->b;
}
}
// begin test
echo "<br>test reads: " . $test_reads;
echo "<br>test assignments: " . $test_assignments;
echo "<br>test globals: " . $test_globals;
echo "<br>test functions: " . $test_functions;
echo "<br>";
for ($z=0;$z<10;$z++)
{
$starta = microtime(true);
for ($x=0;$x<100000;$x++)
{
$xr = getArray('aaa','bbb','ccccccccc','ddddddddd','eeeeeeee','fffffffffff');
if ($test_assignments)
{
$xr['e'] = "e";
$xr['c'] = "sea biscut";
}
if ($test_reads)
{
$rt = $x['b'];
$rx = $x['f'];
}
if ($test_functions) { setArrAtoB($xr); }
if ($test_globals) { $rf = glb_arr(); }
}
$ta = $ta + (microtime(true)-$starta);
echo "<br/>Array time = " . (microtime(true)-$starta) . "\n\n";
$startc = microtime(true);
for ($x=0;$x<100000;$x++)
{
$xo = new TestObject('aaa','bbb','ccccccccc','ddddddddd','eeeeeeee','fffffffffff');
if ($test_assignments)
{
$xo->e = "e";
$xo->c = "sea biscut";
}
if ($test_reads)
{
$rt = $xo->b;
$rx = $xo->f;
}
if ($test_functions) { $xo->setAtoB(); }
if ($test_globals) { $xf = glb_cls(); }
}
$tc = $tc + (microtime(true)-$startc);
echo "<br>Class time = " . (microtime(true)-$startc) . "\n\n";
echo "<br>";
echo "<br>Total Array time (so far) = " . $ta . "(100,000 iterations) \n\n";
echo "<br>Total Class time (so far) = " . $tc . "(100,000 iterations) \n\n";
echo "<br>";
}
echo "TOTAL TIMES:";
echo "<br>";
echo "<br>Total Array time = " . $ta . "(1,000,000 iterations) \n\n";
echo "<br>Total Class time = " . $tc . "(1,000,000 iterations)\n\n";
// test functions
function getArray($a,$b,$c,$d,$e,$f)
{
$arr = array();
$arr['a'] = $a;
$arr['b'] = $b;
$arr['c'] = $c;
$arr['d'] = $d;
$arr['d'] = $e;
$arr['d'] = $f;
return($arr);
}
//-------------------------------------
function setArrAtoB($r)
{
$r['a'] = $r['b'];
}
//-------------------------------------
function glb_cls()
{
global $xo;
$xo->d = "ddxxdd";
return ($xo->f);
}
//-------------------------------------
function glb_arr()
{
global $xr;
$xr['d'] = "ddxxdd";
return ($xr['f']);
}
//-------------------------------------
?>
тестовые чтения:1 тестовые задания:1 глобальные переменные для тестирования:1 функции тестирования:1
Время работы с массивом = 1,58905816078 Время занятий = 1,11980104446 Общее время работы с массивом (на данный момент) = 1,58903813362 (100 000 итераций) Общее время занятий (на данный момент) = 1,11979603767 (100 000 итераций)
Время работы с массивом = 1,02581000328 Время занятий = 1,22492313385 Общее время работы с массивом (на данный момент) = 2,61484408379 (100 000 итераций) Общее время занятий (на данный момент) = 2,34471416473 (100 000 итераций)
Время работы с массивом = 1,29942297935 Время занятий = 1,18844485283 Общее время работы с массивом (на данный момент) = 3,91425895691 (100 000 итераций) Общее время занятий (на данный момент) = 3,5331492424 (100 000 итераций)
Время работы с массивом = 1.28776097298 Время занятий = 1.02383089066 Общее время работы с массивом (на данный момент) = 5.2020149231 (100 000 итераций) Общее время занятий (на данный момент) = 4,55697512627 (100 000 итераций)
Время работы с массивом = 1,31235599518 Время занятий = 1,38880181313 Общее время работы с массивом (на данный момент) = 6,51436591148 (100 000 итераций) Общее время занятий (на данный момент) = 5.94577097893 (100 000 итераций)
Время работы с массивом = 1.3007349968 Время занятий = 1.07644081116 Общее время работы с массивом (на данный момент) = 7.81509685516 (100 000 итераций) Общее время занятий (на данный момент) = 7,02220678329 (100 000 итераций)
Время работы с массивом = 1,12752890587 Время занятий = 1,07106018066 Общее время работы с массивом (на данный момент) = 8,94262075424 (100 000 итераций) Общее время занятий (на данный момент) = 8.09326195717 (100 000 итераций)
Время работы с массивом = 1.08890199661 Время занятий = 1.09139609337 Общее время работы с массивом (на данный момент) = 10.0315177441 (100 000 итераций) Общее время занятий (на данный момент) = 9.18465089798 (100 000 итераций)
Время работы с массивом = 1,6172170639 Время занятий = 1,14714384079 Общее время работы с массивом (на данный момент) = 11,6487307549 (100 000 итераций) Общее время занятий (на данный момент) = 10.3317887783 (100 000 итераций)
Время работы с массивом = 1,53738498688 Время занятий = 1,28127002716 Общее время работы с массивом (на данный момент) = 13,1861097813 (100 000 итераций) Общее время занятий (на данный момент) = 11.6130547523 (100 000 итераций)
ОБЩЕЕ ВРЕМЯ:Общее время работы с массивом = 13.1861097813 (1 000 000 итераций) Общее время занятий = 11.6130547523 (1 000 000 итераций)
Таким образом, в любом случае разница довольно незначительна.Я был очень удивлен, обнаружив, что как только вы начинаете получать доступ к вещам глобально, занятия на самом деле становятся немного быстрее.
Но не доверяй мне, делай это для себя.Лично я теперь не чувствую никакой вины за использование классов в моих высокопроизводительных приложениях.:D
@Ричард Варно
Я запустил ваш точный код (после исправления небольших ошибок) и получил результаты, сильно отличающиеся от ваших.Классы часто запускались при моей установке PHP 5.3.17.
Время в массиве = 0,69054913520813 Время в классе = 1,1762700080872
Общее время работы с массивом (на данный момент) = 0,69054508209229 (100 000 итераций) Общее время работы с классом (на данный момент) = 1,1762590408325 (100 000 итераций)
Время в массиве = 0,99001502990723 Время в классе = 1,22034907341
Общее время работы с массивом (на данный момент) = 1,68055605888837 (100 000 итераций) Общее время работы с классом (на данный момент) = 2,3966031074524 (100 000 итераций)
Время в массиве = 0,99191808700562 Время в классе = 1,2245700359344
Общее время работы с массивом (на данный момент) = 2,6724660396576 (100 000 итераций) Общее время работы с классом (на данный момент) = 3,6211669445038 (100 000 итераций)
Время в массиве = 0,9890251159668 Время в классе = 1,2246470451355
Общее время работы с массивом (на данный момент) = 3,661484003067 (100 000 итераций) Общее время работы с классом (на данный момент) = 4,8458080291748 (100 000 итераций)
Время в массиве = 0,99573588371277 Время в классе = 1,1242771148682
Общее время работы с массивом (на данный момент) = 4,6572148799896 (100 000 итераций) Общее время работы с классом (на данный момент) = 5,9700801372528 (100 000 итераций)
Время в массиве = 0,88518786430359 Время в классе = 1,1427340507507
Общее время работы с массивом (на данный момент) = 5.5423986911774 (100 000 итераций) Общее время работы с классом (на данный момент) = 7.1128082275391 (100 000 итераций)
Время в массиве = 0,87605404853821 Время в классе = 0,95899105072021
Общее время работы с массивом (на данный момент) = 6,4184486865997 (100 000 итераций) Общее время занятий (на данный момент) = 8,0717933177948 (100 000 итераций)
Время в массиве = 0,73414516448975 Время в классе = 1,0223190784454
Общее время работы с массивом (на данный момент) = 7,1525888442993 (100 000 итераций) Общее время работы с классом (на данный момент) = 9,0941033363342 (100 000 итераций)
Время в массиве = 0,95230412483215 Время в классе = 1,059828042984
Общее время работы с массивом (на данный момент) = 8.1048839092255 (100 000 итераций) Общее время работы с классом (на данный момент) = 10.153927326202 (100 000 итераций)
Время в массиве = 0,75814390182495 Время в классе = 0,84455919265747
Общее время работы с массивом (на данный момент) = 8,8630249500275 (100 000 итераций) Общее время занятий (на данный момент) = 10,998482465744 (100 000 итераций) ОБЩЕЕ ВРЕМЯ:
Общее время работы с массивом = 8,8630249500275 (1 000 000 итераций) Общее время занятий = 10,998482465744 (1 000 000 итераций)