Контент


Небольшой практикум по Ko3

Помнится, как-то samsoir, один из core-разработчиков Kohana, задал на официальном форуме задачку: привел кусок кода и попросил найти слабые места в нем (дыры в безопасности, пути оптимизации в целом). Мне понравилась эта идея и вот я попробую открыть аналогичный цикл в моем блоге.

Итак, вот небольшой класс, взятый отсюда (привет, rafi!):

class Num extends Kohana_Num {
 
	/**
	 * Returns a human readble number
	 *
	 * @param  int    a number
	 * @param  int    thousands
	 * @return string
	 */
	public static function human($val, $thousands = 0)
	{
		if($val >= 1000)
		{
			$val = Num::human($val / 1000, ++$thousands);
		}
		else
		{
			$unit = array('','k','mil','t','p','e','z','y');
			$val = round($val,2) . ' ' . $unit[$thousands];
		}
		return $val;
	}
}
 
// End Num

Что, по-вашему, тут стоит исправить?

PS. Дабы не плодить гигантские портянки с кодом в комментариях, размещайте ваши варианты на соответствующих сервисах типа http://pastie.org или http://pastebin.com.

Google Bookmarks Digg Reddit del.icio.us Ma.gnolia Technorati Slashdot Yahoo My Web News2.ru БобрДобр.ru RUmarkz Ваау! Memori.ru rucity.com МоёМесто.ru Mister Wong

Опубликовано в практикум.

Теги: , .


Комментарии (15)

Будьте в курсе обсуждения, подпишитесь на RSS ленту комментариев к этой записи.

  1. php code пишет:

    не совсем понятно с array(»,’k',’mil’,'t’,'p’,'e’,'z’,'y’)

    я бы решал эту задачу без рекурсии
    http://pastie.org/1011749

  2. biakaveron пишет:

    Навскидку — предполагаю, что этот код будет выполняться бесконечно ;)
    но хорошо, одна проблема обнаружена, это нежелательная рекурсия.

  3. stalker пишет:

    @php code
    Для таких вещей [$num = $num / 1000;] правильнее использовать сокращенную запись [$num /= 1000;].

    @biakaveron
    Кодить лень – предполагаю, что код и *rafi*, и *php code* не работает с отридцательными числами.

  4. biakaveron пишет:

    Ну, насчет «правильнее» я не соглашусь — это просто короче :)
    А кодить совсем необязательно. В принципе, обсуждается алгоритм, так что можно и на словах. Замечание по поводу отрицательных чисел принято.

  5. stalker пишет:

    Это не «просто короче» — это интуитивнее, читабильнее и .. короче :) Чем меньше нагромождение дублируемых кусков кода, тем меньше ошибок.

  6. biakaveron пишет:

    Не соглашусь. Полная версия выглядит понятнее, про дублирование в данном случае говорить как-то неуместно, нет? Хотя конечно это не означает, что я не использую подобные «сокращалки» ;)

  7. stalker пишет:

    ну, хз .. ИМХО, лаконичность кода — отражает и знаниие языка(ов), и опыт его использования. (это я как TeamLead маленько понудил :) )

    а про дублирование — в слове из 3-х букв (при особом умении) можно сделать 3-и ошибки .. которые кому-то придется искать и исправлять. с другой стороны — использование специфических особенностей языка(ов) делает код менее читабельным для noob’ов.

    PS: как обычно каждый останется при своем :)

  8. avis пишет:

    Как заметил stalker, отрицательные числа не учитываются. Проверять нужно модуль числа. Так же, нужно исключить числа, что будут больше предлагаемого хелпером диапазона (>=10^23).

    версия с проверкой и минус рекурсия

  9. stalker пишет:

    @avis
    1. в версии без рекурсии параметр $thousands лишний.
    2. я бы запомнил знак числа и abs($val) в начале функции, и везде использовал только $val. а вернул: return ($sign * $val);

    PS: но (2) из области оптимизации, которую еще необходимо тестировать на производительность.

  10. biakaveron пишет:

    Предложу свой вариант:

    1. Учитываем размерность массива с единицами измерений
    2. Работаем и с отрицательными величинами
    3. Отбрасываем рекурсию
    4. Проверяем входные параметры (все врут (с))
    5. Добавил параметр $step, так сказать на будущее.

    Вообще напрашивается создание некоего полуабстрактного метода с километром параметров (начальное смещение $thousands, шаг $step, единицы измерения $units), и отдельных специализированных методов типа human_thousands(), human_bits() и т.д. Например, для физических величин (давление, скорость и т.д.) мы ведь не будем каждый раз писать новые методы с одним и тем же алгоритмом? :) Кстати, можно добавить и мультиязычность — обернуть значения из $units в вызов __().

    @stalker
    Полагаю, что подобная оптимизация из разряда «на спичках».

  11. stalker пишет:

    @biakaveron
    ага, это зависит от частоты использования данной функции. имеет смысл только при выводе массивов 100k+ значений :) просто, когда часто работаешь с высоконагруженными системами начинаешь везде использовать «оптимизацию на спичках».

  12. avis пишет:

    В целом — отличная тема вести такие практикумы. И мозговую деятельность людям позволяет стимулировать и элементы краудсорсинга могут стать полезным для автора.
    Нужно бы сделать такую тему для всего kohana сообщества… :)

  13. Алексей пишет:

    Если вспомнить, что log10 — это число цифр в числе минус 1, то получается вот такой код:
    $unit = array(», ‘k’, ‘mil’, ‘t’, ‘p’, ‘e’, ‘z’, ‘y’);
    $thousands = (int) floor(log10(abs($val)) / 3);
    return ($thousands < count($unit))
    ? round($val / pow(10, $thousands * 3), 2).' '.$unit[$thousands]
    : (string) $val;

  14. biakaveron пишет:

    @Алексей
    Ну, не совсем конечно число цифр (если только после округления в меньшую сторону), но вариант весьма интересных хотя бы своей нетривиальностью. Жалко, что если я напишу такой код, то через полгода придется потратить полчасика, чтобы «вкурить», что это я там написал :) Но уже сам по себе уход от циклов (не говоря про рекурсию) впечатляет.

    Кстати, посмотрел в код Ko3, метод text::bytes() — там тоже логарифм используется.

  15. Алексей пишет:

    @biakaveron
    Для вывода чисел логарифмы — самое то. Особенно при построении графиков, если нужно подобрать круглый шаг (5, 10, 20, 100 и т.д.) для подписей на осях.



Можно включить подсветку кода: <code><pre lang="">...</pre></code>
Разрешены некоторые HTML теги

или используйте trackback.