Tell-dont-ask princible использует больше памяти, как сделать компромисс?
class Operation
{
private $op;
public function __construct()
{
$this->op = [];
for ($i = 1; $i < 1000; $i++)
{
$this->op[] = rand(1,9999);
}
}
public function getOps()
{
return $this->op;
}
}
class TestTellDontAsk
{
public function doItBAD(Operation $op)
{
foreach($op->getOps() as $item)
{
echo $item.'; ';
}
}
public function doItGOOD(array $ops)
{
foreach($ops as $item)
{
echo $item.'; ';
}
}
}
$m = [
memory_get_peak_usage(true),
memory_get_peak_usage(false),
memory_get_peak_usage(true),
memory_get_peak_usage(false)
];
$op = new Operation();
switch(mt_rand(0,1))
{
case 0: (new TestTellDontAsk())->doItBAD($op); break;
case 1: (new TestTellDontAsk())->doItGOOD($op->getOps()); break;
}
echo '<hr>';
echo memory_get_peak_usage(true) - $m[0].'<br>';
echo memory_get_peak_usage(false) - $m[1].'<br>';
echo memory_get_peak_usage(true) - $m[2].'<br>';
echo memory_get_peak_usage(false) - $m[3].'<br>';
это демонстрирует все в ПЛОХОМ и ХОРОШЕМ использовании.
doItBAD()
плохо, потому что передача объекта является ненужным знанием для функции, но MEMORY-GOOD, поскольку она просто передает ссылку, а не весь массив
doItGOOD()
это хорошо, потому что он передает только массив, но MEMORY-BAD, так как он просто передает все данные вместо ссылки.
Теперь, как решить, какой использовать?
1 ответ
Это гораздо более широкий вопрос, чем просто "говори, не спрашивай". Здесь у вас есть две концепции. Очень часто приходится торговать друг против друга.
- Хороший дизайн программного обеспечения
- Эффективный дизайн программного обеспечения
Обе концепции субъективны. То, что составляет хороший код, обсуждается бесконечно. "Эффективное" программное обеспечение имеет несколько различных значений в зависимости от контекста (например: эффективное на процессоре или эффективное на памяти).
Поэтому любой ответ на этот вопрос БУДЕТ СУБЪЕКТИВНЫМ И ОТКРЫТЫМ. Некоторые скажут, что это не очень хороший вопрос переполнения стека.
Когда писать "менее хороший" код для эффективности?
Это опыт.
Если у вас нет опыта, вот несколько советов о том, что думать:
- Насколько критичен этот код для производительности? Будет ли он выполняться один раз в день или миллиард раз в день с миллионами одновременных потоков?
- Насколько велика производительность? Не стоит беспокоиться о потере 1-секундного процессорного времени в день. Не стоит беспокоиться о лишних килобайтах оперативной памяти. Но если этот код представляет собой разницу между 500 МБ или 1/2 МБ, то, возможно, вам следует подумать немного более тщательно.
- Насколько ты нарушаешь принципы? Если 9/10 функций в классе берут объект, и только одна может взять только массив, то вряд ли вы значительно улучшите свой код. Возможно, вы нарушаете принцип наименьшего удивления.
- Время разработки. Допустим, ваше время оплачивается по 100 долларов в час? Стоит ли искать идеальный ответ на этот вопрос за 2 часа вашего времени, когда за 5 минут можно было бы получить несовершенный ответ? Иногда ответом будет "ДА!". Очень часто ответ "нет".
Практическое правило
ПЛОХО: Если у вас нет требований к производительности, никогда не беспокойтесь о производительности. Я провел слишком много лет, исправляя код этих людей. Это ложная экономика.
ЛУЧШЕ: Если у вас нет особых причин беспокоиться о производительности, тогда не... Но тестируйте производительность по ходу дела. Таким образом, ваш код может действительно работать, когда он будет запущен в производство.
Более ясно: стремитесь к хорошему дизайну за счет производительности. Стремитесь к производительности, когда вам нужно.