Pull to refresh
50
1.1

Пользователь

Send message
это так, пока вы остаетесь единственным автором, т.е. не принимали патчи со стороны (если так, то зачем вам опенсорц?). как только в проекте появляются сторонние патчи, то вопрос авторства сильно усложняется. а следовательно и — смены политики лицензирования.
В крупных конторах для этого есть специальные люди, которые занимаются тем, что пишут…

спецификации. тесты это переложение спецификаций в программный код.
Согласитесь, если класс на 100 строк, то писать тесты на 200 строк кажется лишней тратой времени

Часто встречаются штуки, которые проще написать, чем описать. Кстати, пример калькулятора из их числа. :)
* @assert (15,0) == 0.
*/
public function div($a,$b)



/**
* Generated from @assert (15,0) == 0.
* @expectedException Exception
*/
public function testDiv4()

Вот это полная хрень. Если в спецификации написано «assert (15,0) == 0», значит функция div при аргументах 15 и 0 _обязана_ вернуть 0. И Netbeans генерировал правильный код теста. Но Вы, вместо того, чтобы исправить реализацию, всех обманули, переделав сам тест.

Условие неверных спецификаций не рассматриваем, по очевидным причинам.
Вам и вам предлагается один и тот же стимул.

Это абстрактная ситуация. На практике такое сложно представить. Я, печатаю это сообщение, долбя по клавишам ноута. А Я, сидящий в метре от ноута уже не способен дотянуться до клавиш, и занимается совсем другими делами. :) Эта хабра-страничка, создается одним и тем же алгоритмом, но выглядит по-разному для каждого пользователя, из-за одного мелкого нюанса — куки. Ну и т.п.
У них все правильно написано: 4 nginx'а (фронтенда) кормят запросами 1 сервер торнадо (бекенд). Дело в том, что «hello, world» отдается бекендом гораздо быстрее, чем форнтенд справляется с обслуживанием подключений клиентов. Поэтому, в одиночку, фронтенд не способен нагрузить бекенд полностью. Хотя на 4-х ядрах логичнее было бы пускать 3+1.
Торнадо стоит использовать в тех случаях, когда есть возможность создания неблокирующихся обработчиков запросов. Чтиво по этой теме: twistedmatrix.com/projects/core/documentation/howto/async.html
У приложений Django иная модель обработки запросов.
Тут говорится о возможности запускать приложение tornado при помощи стороннего сервера wsgi (вместо встроенного). Но при этом теряются асинхронные фичи. Т.е. речь идет о том, что приложение торнадо может быть wsgi _клиентом_.

Джангу под торнадо вы не запустите. Торнадо не является wsgi сервером.
NS славится чертовски легкими select'ами, с поиском по эффективному ключу. NI добавляет легкие вставки.

В предлагаемом (защищаемом? ))) Вами методе:
* для select необходим тяжелый inner join таблицы иерархии самой на себя.
* присутствует бОльшая избыточность. Хотя программно используется лишь один запрос на вставку, база вставляет несколько записей (для которых нужно создать индекс и все это писать на диск).
* Если в колонке таблицы многократно дублируются одни и те же значения, то индексы теряют эффективность.
Все это вместе делает способ представления данных не эффективным.
Не ясно, чем задается прядок узлов в дереве.
Про дополнительную таблицу, простите, не понял…
Тяжелые вставки. Не говоря уже о перемещениях (хотя, фиг с ними, с перемещениями, это не часто нужно).
В классических netsted sets вставка узла заставляет пересчитывать все правое поддерево. Достаточно даже небольшого количества одновременных запросов пользователей на добавление узла, чтобы база просела. Я имею ввиду, например, комменты.
А еще есть Netsted Intervals, у которых этих недостатков меньше, благодаря тому, что left и right задаются рациональными числами. Статья:
www.dbazine.com/oracle/or-articles/tropashko4, математика: arxiv.org/abs/0806.3115v1
Можно багрепорт? :)
  """Использовать регулярку не хотелось бы для одного поиска"""
    translated_text=answer[index:answer.find("</div", index)]
    translated_text=replace_html_mnemonics(translated_text)
    translated_text=translated_text.decode("koi8-r")

А почему koi8-r? В answer есть указание на кодировку страницы в виде.
<meta content="text/html; charset=UTF-8" http-equiv="content-type"/>

Мне вот такое выдал… Дергайте от charset= и до " и передавайте значение в translated_text.decode(). Хотя идеологически правильнее было бы декодировать сам answer, прежде чем разгребать.
В убунте еще StarDict, умеет переводить, используя google. Нужно приложить вот такой патч:
#! /bin/sh /usr/share/dpatch/dpatch-run
## google.dpatch by  <funca@localhost>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: No description.

@DPATCH@
diff -urNad stardict-3.0.1~/src/stardict.cpp stardict-3.0.1/src/stardict.cpp
--- stardict-3.0.1~/src/stardict.cpp	2007-11-05 08:39:51.000000000 +0500
+++ stardict-3.0.1/src/stardict.cpp	2009-08-22 23:36:01.000000000 +0600
@@ -1943,7 +1943,7 @@
 			}
 		}
 	} else if (engine_index == 0) {
-		#define GoogleTranslateStartMark "<div id=result_box dir=ltr>"
+		#define GoogleTranslateStartMark "<div id=result_box dir=\"ltr\">"
 
 		char *p = g_strstr_len(buffer, buffer_len, GoogleTranslateStartMark);
 		if (p) {

сразу подумалось об обратном — модуле к fuse, монтирующим форумы (phpbb2, скажем) как файловую систему. %)
база не позволяет сделать поле `Path` длиннее 1000 символов (#1071 — Specified key was too long; max key length is 1000 bytes), что значит, что, если у нас средняя длина ID будет 4 символов мы не сможем делать деревья глубже 1000/(4+1), то есть самое глубокое возможное дерево в таком случае — 200 элементов. и 166 при средней длине ключа 5 цифр (если на сайте более 50000 комментариев в среднем)

Materialized path можно строить иначе. В таблице, описывающией иерархию будем хранить ссылку на объект (ElemId) и путь (Path).
ElemId, Path

В каждом сегменте пути будем записывать номер узла в поддереве по порядку (а не ElemId). И сделаем размер сегмента пути фиксированной длины (скажем 3 символа), чтобы сортировка по такому пути выдавала нам дерево в естественном порядке.
"000" -- первый уровень
"000000" -- второй уровень
"000001000"
"000001001"
"000002"
"001"
"002"

Уровень узла в таком дереве вычисляется по формуле Level = strlen(path) / 3.

Сейчас в каждом поддере можно создать не более чем 10^3 = 1000 узлов. Но если увеличить основание системы счисления, то емкость дерева возрастет. В php функция base_convert позволяет увеличить базу до 36. Т.е. емкость уже составит 36^3 = 46656. Для комментов этого достаточно. И размер пути получается небольшим. 1000 символов хватит для кодирования 1000/3 = 333 уровней. Ну, а скажем путь к комменту на 20-м уровне составит 20*3 = 60 символов. В MySQL есть аналогичная функция. Поэтому всю математику связанную с пересчетом пути при модификации дерева можно записывать прямо в запросе.

Конкретно под комментарии стратегию создания пути можно еще оптимизировать. Понятно что, чем глубже уровень, тем меньше «ветвистость» комментов. Максимальное число комментов стоит ожидать лишь на первом уровне. Поэтому только у первого сегмента пути оставим длину 3 символа. А остальные сегменты можно сократить и до 2-х. 1296 комментов на подуровне хватит заглаза. Таким образом путь к комменту на 20 уровне будет составлять всего 41 символ.
"000" -- первый уровень
"00000" -- второй уровень (2 символа в сегменте)
"0000100"
"0000101"
"00002"
"001"
"002"

Да, нужно обязательно ограничить длину индекса в таблице MySQL, для поля Path. Это не сильно скажется на производительности, зато позволит прилично сэкономить по памяти.
вот что интересно. если приложение чисто вычислительное (рассчитывает координаты сферического коня в вакууме, или отдает «Hello, World!» :) ), то использование ниток или процессов производительности не прибавляет, а даже наоборот. процессор все равно один и лишние переключения контекста ни к чему. другая картина получается, когда приложение часть времени проводит в ожидании (синхронного ввода-вывода, результата sql запроса, или стоит таймаут на пару секунд :) ). в это время процессор не задействован, сервер может обрабатывать другие соединения. картина производительности будет иная.
серверы, использующие событийную модель, как лицензия gpl: заражают ей все приложение. :)
вот любопытно. если разделить transfer rate (клобайт/сек) на request per seconds, то получим килобайт / запрос.
1014,09	/ 3484,67	0,291
754,55	/ 3140,87	0,240
720,04	/ 3262,5	0,221
654,98	/ 1202,8	0,545
639,66	/ 2651,86	0,241
171,23	/ 712,78	0,240

интересно, что у «flup 2 процесса / 5 тредов» эта величина больше чем у других конфигураций в два с небольшим раза. он что, строчку «Hello World!» отдает в юникоде? =)
Вот так, через дом2:
<a id='target'>click me</a>

$('#target').get(0).addEventListener('click', function(e) { window.console.log('test1') }, false)
$('#target').get(0).addEventListener('click', function(e) { window.console.log('test2'); throw "Error1"; }, false)
$('#target').get(0).addEventListener('click', function(e) { window.console.log('test3') }, false)

...
test1
test2
test3
Error!

Логика диспетчеризации запроса для получения свойства с использованием прототипа, примитивна до безобразия:
— Эй, Объект, гони сюда свойство property!
— Хм… а нету… (если есть, был обязан выдать)
— Тогда пусть вернет тот, кто тебя породил, такого урода! (объект бежит просить в словаре у своего конструктора)

Если и у конструктора такого свойства нет, то обычно, на этом все и заканчивается, ибо конструктор конструктора уже не при делах: «вассал моего вассала не мой вассал». Это все, что доступно в JS.

Диспетчеризация запроса по иерархии классов отражает совсем другое отношение: конкретное-общее (класс -> супер-класс) — и логика диспетчеризации запросов тут совершенно иная. Единственное что их роднит с «объект-конструктор», это транзитивное отношение «instanceOf», которое может означать и «объект типа», и «объект класса» (см. диаграмму www.cafepy.com/article/python_types_and_objects/images/relationships_transitivity.png). Но из-за этого «двойного» смысла и возникает путаница, будто одно можно выразить через другое. Это не так (не даром, на диаграмме стрелки выглядят по разному).

Information

Rating
1,130-th
Location
Екатеринбург, Свердловская обл., Россия
Date of birth
Registered
Activity