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 минут можно было бы получить несовершенный ответ? Иногда ответом будет "ДА!". Очень часто ответ "нет".

Практическое правило

ПЛОХО: Если у вас нет требований к производительности, никогда не беспокойтесь о производительности. Я провел слишком много лет, исправляя код этих людей. Это ложная экономика.

ЛУЧШЕ: Если у вас нет особых причин беспокоиться о производительности, тогда не... Но тестируйте производительность по ходу дела. Таким образом, ваш код может действительно работать, когда он будет запущен в производство.

Более ясно: стремитесь к хорошему дизайну за счет производительности. Стремитесь к производительности, когда вам нужно.

Другие вопросы по тегам