Перейти к контенту

Язык Lua. Общие вопросы программирования


Malandrinus

Рекомендуемые сообщения

Из шапки, дабы немного удовлетворить любопытство:

--[[---------------------------------------------------------------------
Библиотека универсального хранилища данных произвольного размера
Основана на использовани нетпакетов объектов (используется новый тип 
объектов, описанный в конфигах, имеющие произвольную длину пакета).
Хранилище подстраивается под размер хранимых данных.

Использовать можно только после загрузки игры (присутствует актор)
Удаление переменной производится так же, как и установка переменной - 
функцией set, как значение надо передать nil
Получение переменной производится функцией get, второй параметр - 
значение по-умолчанию (опциональный параметр). Если переменной не 
существует и не указано значение по-умолчанию, будет возвращен nil

Сразу после загрузки хранилища "кидается" событие storage_load
Непосредственно перед сохранением - storage_save

Разрешено хранить переменные следующих типов:
    булевое (хранится как байт)
    
    число (хранится всегда как float, если требуется хранение очень 
        больших чисел, то рекомендуется использовать хук приведения
        к строке: ""..1234567890 - передавать на вход set)
        
    строка (хранится как последовательность байт + нулевой символ, 
        конец строки; ограничение на длину строки - 8000 байт)
        
    таблицы (ПРОСТЫЕ! То есть: без метатаблиц, без нулевых символов и 
        прочих бинарных данных, без рекурсий и только с простыми типами 
        в ключах и значениях. Кроме того, объем таблицы очень сильно
        ограничен - при сериализации строка должна влазить в пакет, а 
        значит ограничение примерно в 8000 байт текста.)
    
Depends on:
    xs_sandbox
    xs_helpers (as sandbox's module)
--]]---------------------------------------------------------------------

 

 

Viнt@rь, я не имею ни малейшего понятия, что там в АМК ЗП :) Я его в глаза не видела.

То, что я сделала - не является замещением pstor. Это просто отдельное хранилище, которое можно использовать под различные нужды

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Viнt@rь, нет, не помог :)

Это условие не совсем корректное, но меня устраивает. Дело в том, что мне нужна гарантия, что все серверные объекты уже зарегистрированы. Учитывая, что в онлайн первым переходит актор, то делает это он сразу как раз после этой самой регистрации, что мне и требуется.

 

ЗЫ А что там в АМК ЗП?

 

Добавлено через 1 мин.:

abramcumner, не поняла вопроса.

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Viнt@rь, ага, поняла. Нет, у меня нет никаких файлов. Механизм попроще, и как разделять, какое хранилище для какого сейва простым способом (в амк)?

Что касается колбека, то именно на появление актора производится инициализация хранилища, раньше - нет, так как я не могу гарантировать его полную загрузку.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

abramcumner, увидишь, все просто, но достаточно эффективно. ;)

 

 

Добавлено через 2 мин.:

Artos, не злись! :-P Оказалось, что актуальные, ага. Только толку ноль.

Что касается совместимости: ты опять делаешь убер-пупер-мега-скрипт :) Я не поддержу дискуссию.

ЗЫ Чтобы посмотреть библиотеку пакетов, качать почти 200 метров...

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Artos, Пожалуй, попрошу тебя выложить куда-нибудь этот скрипт, если тебя не затруднит. Остальное мне не нужно, да еще из db выковыривать.... Увольте :)

Неактуально. Посмотрела. Нет у Artos'a ветвления по физ флагам

 

Добавлено через 2 мин.:

Viнt@rь, ну тогда я предполагаю ситуацию: сохранили что-то в хранилище, загрузили другой сейв, а в хранилище данные, которые от другого (ну то, что записали до этого). Тут нужен механизм разделения данных, а еще бы неплохо отслеживать удаление сейвов... В общем, тоже хлопоты, правда другого рода и нет ограничений на длину данных (одного значения)

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Я основывала ответ на том, что у меня есть. Я признала неправоту, чего тебе еще надо?

И не надо мне про поиск, раз речь шла про актуальную версию. Откуда мне знать, что у тебя в загашнике припрятано по этому поводу?

И да, делай. Моя позиция отличается. Если делается мод, то он затачивается под определенную версию или диапазон. Кроме того, то, что выложено точно так же расширяется вплоть до повторения функционала универсального АСДС. И если руки прямые, то сделать это просто. Мне не нужны универсальные, мне нужны для работы с ТЧ. Я озаботилась тем, чтоб они у меня были.

И еще раз: не только сам скрипт, а еще и то, как реализовано я выложила на суд.

 

ЗЫ вот потому как ты реагируешь, я и не хочу с тобой поддерживать дискуссию. Сорри за офтоп.

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Ой ли, "стандартный" ли? Ты хочешь сказать, у него так, мелочевка всякая? :) Это отдельный разговор про фломастеры.

И даже не об у ниверсальности идет речь. Мой скриптик с таким же успехом меняется легко и непринужденно, только пропишите (зависит от нужд автора) и будет счастье, главное руки прямые.

Вопрос: удобство использование (внешний интерфейс), возможность простоты расширения (в том числе и не профи, а по определенным правилам типа "скопируй вставь"), возможность использовать отдельно, без дополнительных связей. Это относится к любому программному коду, который создается и обсуждается.

Вот честно, Artos опять наверняка воспримет за наезд, код симбиона охрененно трудно сопроводжаемый не автором. А тут речь идет об инструментах, которые могут помочь и не очень продвинутым программистам реализовывать что-то, в частности то, для чего своих умений не хватает.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Ага ага :) Всего лишь скопировать. Все время слышно "а у меня", "а в моем моде"...

Вопрос простой: если у тебя такой гениально простой интерфейс, то почему лично я знаю людей, которые НЕ ПОНИМАЮТ, что оно делает и как ваще с ним работать. И так же я знаю людей, которые отказываются от использования твоей библиотеки впользу более простых решений.

Почему такое происходит? ;)

 

Добавлено через 3 мин.:

Andrey07071977, значит восприятие у вас схожее или не было примеров более читаемого кода.

Комментарии, которые должны помогать, наоборот засоряют код и так дале...

Но в топку симбион. Это мод, а не сабжект топика. Сабжект - Lua, общие вопросы программирования.

Тему я покинула, в плане обсуждения симбиона и "мое, а у меня". Я поделилась своим "мое, а у меня". Будет фидбек - будет здорово.

Тем более, что уже нашлось несколько ошибок, сразу исправленных.

 

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение
- что и является одной из лучших защит как от ковыряния неумелыми руками, так и от тупого копипаста.

Те, у кого свои руки есть, копипастить это не будут, проще свое написать, которое тоже велосипедное, но более понятное автору.

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение
Artos забыл добавить required brain.script в начале модуля, от того и происходит tongue.gif - под снос, plz

Ну да, посему давайте будем говорить всем желающим "обнови hand.sys"? Негоже...

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение
это гораздо проще мнгих других вариаций, как и твоей сегодняшней

Не суди, да не судим будешь :) Сам то всегда пытаешься показать, что просто умнее всех в сталкеромодоводстве.

И уж не тебе решать, проще или нет, а людям, которые буду использовать. И дело не во внутренностях, а именно в том, с чем люди будут работать.

Засим, пожалуй, я буду тебя игнорировать. Ибо меня подавляет твое ЧСВ, вот честно.

 

ЗЫ Да, переход на личности, возможно. Просто это очень утомило. Я не к вам, ув. Артос пришла, чтоб меряться тем, чего у меня нет. Я выложила то, что попадает под сабжект топика. Вас же, уважаемый, я буду игнорировать, пока более конструктивного чего-нибудь не услышу. Желаетельно без контекста "мое, а у меня". Если вы не хотите выучить и узнать что-то новое, да еще на примерах, не навязывайте свою дремучесть другим.

 

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

*Shoker*

Про снижение полезности я не соглашусь. Что вы туда собрались писать? Войну и мир по буквам? :)

Я исхожу из простых соображений практичности. Если вспомнить, какого рода данные обычно помещают в такое хранилище, то эти ограничения выбираются ой как не скоро. Я исхожу из реальных условий, а не теоретических. В теории, даже такое ограничение - пустяк. Стоит столкнутся с ним и тогда можно задумываться, как это решить. Можно разбить таблицу на две и сохранить под ключами с суффиксами. Да много решений, главное включить фантазию.

 

KD87, спасибо. Остался вопрос - речь идет о стейт части или апдейт части (думаю стейт, но уточню)? Я бы не сказала, что АСДС - базовое руководство. Благодаря ему вообще появилась техника работы с пакетами в свое время.

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Хочу немного написать на тему сабжа топика. Несколько раз задавали вопросы о том, как выполнить (к примеру с помощью той же самой песочницы) метод объекта или функцию, хранящуюся в таблице (тоже некое подобие объектов). Точнее - как передать куда-то "ссылку на вызов". Попробую описать на примере, как это сделать просто и без заморочек. Для начала напишу код, который потом разберу (внимание, код написан так, чтобы можно было просмотреть в "чистом" ЛУА, например по этой ссылке - http://www.lua.org/cgi-bin/demo, этот сайт представляет собой обертку для ЛУА-интерпретатора, что лично мне очень помогает отлаживать разный код):

math.randomseed( os.time() )

local mega_object = {
    execute = function (self, max_val)
        return math.random(1, max_val or 10)
    end
}

local mega_object2 = {
    execute = function (self)
        return "non random; string"
    end
}

function object_execute(obj)
    local _proxy = obj
    local function _call(...)
        return _proxy:execute(...)
    end
    return _call
end

local captured_closure1 = object_execute(mega_object)
local captured_closure2 = object_execute(mega_object2)
local val1 = captured_closure1(1000)
local val2 = captured_closure2(100)

io.write( tostring(val1).."\n" )
io.write( tostring(val2) )

Итак, разбор по строкам:

1 - инициализация генератора псевдослучайных чисел.

3-7 - создаем "объект" с функцией execute, которая генерирует число в диапазоне от 1 до значения параметра, переданного в функцию. Внимание! Первый параметр я назвала self, так как данную функцию я буду вызывать через ":", а не через "." (см. ниже), то есть, по сути так, как работает стандартно вызов методов - первым аргументом передается ссылка на сам объект, у которого метод вызван.

9-13 - аналогично, но создаем объект, который делает в методе execute другую работу - возвращает строку.

 

Итак, есть два объекта со схожим интерфейсом, как сделать так, чтоб можно было передать в виде одной переменной "вызов метода объекта"? mega_object2.execute, например, является функцией, но при таком вызове не передается контекст - self, что очень важно, когда надо вызвать именно как метод объекта, а не статическую функцию.

Дальше начинается "магия ЛУА", которая позволит "обернуть" обращение к методу объекта в функцию, которую можно записать в переменную или передать куда-то в качестве параметра.

 

15 - начинается код функции (на вход передается объект, который будем "оборачивать"), результатом работы которой станет... другая функция! Функция, которая будет вызывать нам нужный метод у нужного объекта.

16 - создается ЛОКАЛЬНАЯ переменная, которая будет хранить ссылку на наш объект. То, что она локальная, означает, что при каждом выполнении object_execute, будет создаваться новая переменная. Это нужно для...

17 - ... локальной функции _call, которая собственно и вызывает нужный метод execute. То, что мы сейчас сделали, называется замыканием - переменная _proxy будет существовать до тех пор, пока существует функция _call, которая эту переменную использует.

 

У нас получилась матрешка из функций.

 

18 - возвращаем результат работы метода объекта

 

20 - функция object_execute возвращает функцию _call

 

Зачем? А) эта функция при выполнении object_execute каждый раз получается уникальная, переменная _proxy хранит конкретный объект и не может быть перезатерта при следующем вызове object_execute, потому что создается каждый раз заново, а старая остается связана с функцией _сall, созданной при прошлом вызове object_execute. Б) Функция _call оборачивает вызов метода. Таким образом получаем цепочку: object_execute возвращает функцию, которая выполняет метод объекта. Понять сразу сложно, конечно же, поэтому примеры:

 

23 - создаем переменную, в которой будет лежать "вызов метода execute объекта mega_object".

24 - аналогично, только получаем обертку вокруг другого объекта.

 

При этом, прошу обратить внимание, что функция, которая в результате даст нам обертку, - одна, мы просто передаем в нее нужный объект. И в результате получаем две разные функции, которые будут "дергать" один и тот же метод, но у разных объектов.

 

25-26 - как раз выполняем функции-обертки и получаем результат работы методов у разных объектов.

28-29 - вывод результата

------------------------------------

Итак, итог: ЛУА позволяет делать "финты ушами" и довольно просто организовывать работу с методами объектов, передавать их ("ссылки на метод", на деле обертку, но разницы нет) куда угодно, присваивать и т.п.

Применительно к моей песочнице, позволяет подписывать, например, работу определенных методов нужных объектов на разные события. И отписывать тоже.

Возникает закономерный вопрос - зачем такие сложности? Почему не вынести это во внутренности какой-нибудь подсистемы и она бы все делала автоматом. Ответ прост: система не сможет организовать вызов через ":" простым путем, придется громоздить огромное количества кода... Это раз. Такие ситуации, на самом деле, встречаются гораздо реже, чем обращение к "обычным" функциям, которые регистрируются один раз за игровую сессию. Это два. И, наконец, три: никто лучше автора не опишет, что и как там должно происходить при вызове метода. Ничто не мешает не просто вызывать метод нужного объекта, а еще и выполнить какую-то дополнительную работу. Может даже в зависимости от условий, вообще не выполнять. Например, сработал колбек, в нем работа со сталкером, а он к этому моменту оказался мертв. Мы можем сделать соответствующую проверку и отписаться от события.

Последние два абзаца - применение на практике. Но в целом, данная, гм, статья(?), показывает такие возможности ЛУА, как замыкания на живых примерах и в живых ситуациях (вызов методов с сохранением self и делегирование этих "вызовов")

------------------------------------

Материал довольно сложный для понимания, мне кажется, поэтому жду вопросов и постараюсь объяснить нюансы. Отвечать на вопрос, "а нафига это ваще нужно" не буду, так как нафига - описано в самом начале. Раз люди спрашивают, значит вопрос действительно их интересует. Я же постаралась предложить решение. Оно не единственное, но, на мой взгляд, наиболее эффективное и простое - используются только особенности языка.

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Хранилище без завязки с сейвом, на мой взгляд, не имеет большого смысла. А загрузка актора говорит о том, что игровая сессия началась. Или я что-то упускаю?

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Viнt@rь, прав в чем?...

....

Маленькая ремарка. Все, что я здесь выкладываю, не претендует на мега инновацию. Это просто реализации идей, которые я начала 2-3 года назад, но не доделала по тем или иным причинам. И сделано это сейчас совсем иначе, чем я сделала бы тогда. Сделано буквально на коленке в приступе ностальгии в праздничные дни. Выкладывается это именно в этом топике в первую очередь как пример другого подхода к программированию, на ЛУА в том числе. Проблема в следующем: говоришь абстрактные примеры, просят дать жизненный пример, приводишь пример, говорят - а у нас это есть и работает. А ведь вопрос не в том, что есть и работает, а в том, КАК работает. Об этом топик. Да, конечно, примеры живые и используются в живом коде (Artos, кстати, про код говорят в единственном числе, про тот, что пишут программисты. Коды - это могут быть, например, пароли, шифры и т.п. Так, оффтоп), но помимо практики присутствет и теория, про которую тут же забывают. Не спрашивают, что это и как, а спрашивают примерно "а чем это лучше того, что есть, докажите". Никто ничего никому не докажет - это отдельный подход. Кому-то нравится, кому-то нет. Проблема в том, что никому это здесь оказалось не надо. Либо те, кому надо, сидят и молчат :)

...

Кратко по скриптам.

 

Хранилище - ничего революционного. Просто созданы объекты, которые занимаются только этой задачей. ПДА пусть остаются ПДА, а хранилище - хранилищем. Хранить в кастом-дате имеет смысл небольшой объем информации, связанный непосредственно с тем объектом, который информацию хранит. Ничего преступного не вижу и сама это использую (хранение в кастом-дате). Хранилище же абстрактное, для каких-то вещей, не привязанных ни к каким игровым сущностям. Надеюсь, эта идея понятна. Что же касается on_register и тому подобных колбеков, то обычно на этом этапе еще нет надобности что-то выполнять, игра еще не началась. Но гораздо более существенным является то, что пользуясь такими методами, мы не знаем, все ли в хранилище у нас загрузилось или не все - объектов, которые хранят информацию - несколько. Поэтому именно спавн актора - колбек срабатывает одним из первых после процесса регистрации всяческих объектов. Друго дело, что на on_register можно повесить поэтапное заполнение хранилища, но поскольку загрузка идет один раз, то старый-страшный метод перебора тут тоже вполне работает. Следующее - интерфейс. Прост до безобразия, две функции. Собственно и говорить тут не о чем. Тут, кстати, как я поняла, почему-то решили, что ограничение на хранилище - 8кб. Не на хранилище, на одно значение в нем. Если не так поняла, то ок.

 

Таймеры. Тоже абсолютно ничего революционного, кроме такой "маленькой" детали, что таймеры - это объекты. То есть их можно передавать по ссылке и отслеживать их состояние. Если вспомнить самую первую реализацию из АМК, то функция стартовала таймер, потом отследить за его жизнью было тяжело, в хранилище они представлялись пачкой переменных и т.п. То есть основная идея - таймер, как объект, несущий в себе (ООП, как никак) всю необходимую информацию. Вместо вызова функции с 1001 параметром, получаем объект, параметры которого можно менять во время жизни этого объекта. Это важно, на мой взгляд. (Не столько применительно к таймерам, как вообще к идеологии объектов).

 

Пакеты. Как заявили "то же самое, что было в АМК". А покажите-ка мне не то же самое? Это одна и та же техника. Только, опять же, подход другой. Вместо того, чтоб вызывать пачки функций, и таскать тот объект, к которому эти функции применять, создается отдельный объект, который знает, к чему применять, хранит информацию в себе. Его, этот объект, тоже удобно можно передавать как параметр в функции, например, не озадачиваясь тем, чтоб таскать параметром и еще тот объект, к которому это было применено. Наглядный пример - хранилище. Создали объект, а он уже в себе и ссылку на серверный объект содержит и нужный инструментарий. Код становится лаконичнее, интерфейсы - проще. Вот, к примеру, был код для оффлайн-алайфа:

        if IsMonster(obj) then
            local tbl = amkII_rdpk.amkReadMonster(obj)
            tbl.iHealth = health
            tbl.iUpdHealth = health
            amkII_wrpk.amkWriteMonster(tbl, obj)
        elseif IsStalker(obj) then
            local tbl = amkII_rdpk.amkReadStalker(obj)
            tbl.iHealth = health
            tbl.iUpdHealth = health
            amkII_wrpk.amkWriteStalker(tbl, obj)
        end

а стал

        local pk = xs_netpk.monster(obj)
        if not pk:isOk() then
            pk = xs_netpk.stalker(obj)
        end        
        local data = pk:get()
        data.health = health
        data.updhealth = health
        pk:set(data)

Если в первом случае от условий зависит и вызов проверки и выбор двух(!) разных функций для работы с пакетами, то во втором, получив нужное, интерфейс одинаков. Более того, если передать объект и не монстра и не сталкера, второй фрагмент отработает как ни в чем не бывало, никаких ошибок, падений и прочего. Пользователь библиотеки защищен от ошибок. Ему не дадут сделать то, что не предусмотрено. И опять акцентирую - объект. Один раз получив пакет, нам уже наплевать на исходный объект obj. Ссылка на него сохранена и не "потеряется". И еще, тут прозвучало, что сложно и громоздко. Неправда - интерфейс простой. Для конечного пользователя-программиста он очень прост. Все то обилие кода - реализация структур, идентичных структур в движке, что позволяет снизить процент ошибок.

 

Хелперы. Ну тут, думаю, ясно. Из нюансов - расширение функционала стандартных библиотек. И трансляция важных вещей в глобальную область видимости, чтобы вызовы нужных вещей были покороче, чем xs_helpers.trim, например. Станет просто trim, доступное везде, во всех скриптах. Или сериализация таблиц. Ее можно запускать двумя способами (как раз писала про оператор ":"): table.serialize(tbl), а можно tbl:serialize(). Или tbl:clone() - получим клон таблицы, а можно table.clone(tbl). Это уже фокусы самого языка ЛУА. Вообще, очень удобно помнить о таком поведении оператора ":".

 

Песочница. Тут то же самое - работа посредством объекта, который проходит через всю цепочку подписчиков, и посредством которого можно управлять этим процессом. Без объектов это сделать намного сложнее, существенно. При том, что код вдобавок станет монструозным. Что, на мой взгляд, не айс.

 

Итог сей длинной простыни: ООП имеет право на жизнь и в модострое сталкера, только надо понимать его.

На эту тему, спасибо Viнt@rь, я как раз попробую пояснить про псевдо-ООП.

Viнt@rь приводил код из АМК. Не важно, кто автор, что там делается, главное - как. Как вы все знаете, скрипты при загрузке помещаются в отдельный неймспейс, переменную, имеющую имя этого скрипта, все что в скрипте описывается, доступно через эту переменную. Это поведение очень похоже на так называемый синглтон - образец класса (в данном случае не класса, а сущности другой - скрипта) в программе присутствует в единичном числе. Даже если сделать символических ссылок, объект остается тот же. Так вот. Есть скрипт, по сути - синглтон. Внутри описывается класс, создается образец класса, тоже в единственном числе и.... все. Используется. Вопрос - а зачем нужен такой класс тогда? Я могу смело убрать имя класса из функций,вынести содержимое конструктора просто в тело скрипта, а в самом начале скрипта обозначить local self={}. После этого я смогу делать все то же самое и работать оно будет точно так же. Только вызовы функций будут не через ":", а через ".". Но суть не меняется. Я даже выигрываю - чтоб сделать что-то, мне не надо создавать инстанс объекта, я просто сразу вызову нужную функцию. В результате вопрос остается открытым - зачем класс? Зачем объект этого класса?

Второй пример псевдо-ООП (есть скрипт переодевания неписей, вроде оттуда же). Все как и в первом примере, только НИГДЕ не используется self, конструктор пустой, в методах логика, которая проверяет объект, который дают на вход, но хуже всего - таких объектов куча, на каждого непися по штуке. Правильнее делать иначе - в конструкторе передавать объект, и вызывать метод, не указывая, что проверять - объект "проверяльщика" сам будет знать, что проверять. А еще правильнее - оставить логику как есть, ибо она простая до безумия, и избавиться от класса. В результате получим две простых функции.

Все эти доводы можно оспорить. Есть класс и работает. Но проблема в том, что своего прямого назначения такие конструкции, увы, не выполняют (если вспомнить, что такое классы, инкапсуляция, наследование и т.д.)

---------------------------

Прошу прощения за простыню, но, думаю, она по сабжу топика. И надеюсь, что у кого-то в голове сработает понимание, в чем отличие этих двух разных подходов к программированию. И почему я вообще начала про все это говорить. И показывать примеры.

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Ну, про что я и говорила. Посрать на идею, давайте пробелы посчитаем. Мне, может, венгерку припомнить? :) Хехе.

Черт, я ж забыла, что тов. Артоса игнорирую. К сожалению в топике от него никуда не деться. По существу топика постов не вижу. Так что пока. Оставляю паству на ваше попечение, магистр ;)

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Viнt@rь, вот я об этом и писала - "работает же" :) Конечно, переделывать глупо. Надо просто сразу делать с умом.

Еще раз - приятней видеть одним классом. В чем приятность? В именах функций видеть имя класса? :) Сомнительный аргумент, на мой взгляд. Код можно грамотно оформить и без класса, обрамить комментариями, организовать блоки, сделать приватные функции и т.п.

В идеологии сталкера нет "голых" функций. Ты их вызываешь, предварительно указав имя файла. Объединять надо функции семантически - один файл, один набор функций.

Ты сам ведь понимаешь, что дело именно привычки. Но для меня главное, что ты понимаешь, что такое псевдо-ООП. Смею на это надеяться.

 

Gun12, вопрос сразу - это ты делаешь ООП-like, или пользуешься свойством оператора ":" для доступа к "экземпляру"? Поясню, откуда этот вопрос. На самом деле "объект" у тебя тут всего лишь один, а остальное "настройки", которые хранятся в таблице. Поэтому такое решение претендовать на ООП никак не может.

В целом "нарекания" вызывает функция timerCreate - много параметров, которые могут еще и меняться местами (разный набор настроек, я понимаю). Я бы порекомендовала либо использовать один параметр options (хеш-таблица) или использовать chain-calls, несколько методов для настройки, каждый из которых возвращает self. То есть сделать пошаговое создание, так сказать. Но для не объектов (в контексте именно инстансов - у тебя их нет) это не очень удобно. Если кратко - сделай "говорящий" интерфейс: local t = timer():setAction(xxx):setPeriod(xxx):run() примерно так. Запись длиннее, но зато гораздо нагляднее, что происходит именно тут. К такому варианту еще провоцирует даже не количество параметров, а то, что они могут обозначать разное при разных наборах. Ну и, мне кажется, такой подход избавил бы от функций типа changeAction, что привело бы к упрощению интерфейса, а это всегда хорошо. :)

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Вдогонку - ты вполне можешь использовать замыкания для имитации "экземпляров объектов". Я за пару страниц до этого писала, что это за фигулина. В твоем случае, можно за селф принять как раз ту самую локальную переменную и этим пользоваться, аля:

function createTimer(options)
    local self = ... тут создаем как у тебя набор настроек ... 
    self.setAction = function()
        ... что-то делаем и возвращаем селф...
        return self
    end
    ... тут еще интерфейсные функции ...
    return self
end

То есть обернули твою таблицу настроек в интерфейс. Это просто как вариант. Пользуемся, как ты любишь, только "чистым" ЛУА

 

Добавлено через 2 мин.:

На ООП особо не претендую. Изначально хотел сделать меньше записей.

Честно скажу - по мне вышло так наоборот более громоздко, если не пытаться все обернуть в такую вот таблицу. Надо проработать интерфейс - чем меньше методов, тем лучше, чем меньше параметров в них, тем тоже лучше. Говорю как архитектор приложений с пятилетним стажем :) (дада, надо ж похвастаться. Шутка). Просто с простыми вещами (внешне простыми) гораздо комфортнее работать, а код компактнее (опять же - не самих вещей, а тот код, где используются эти вещи)

Изменено пользователем xStream

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Gun12

По идее, правильно делать так, чтоб при срабатывании одного таймера, тут же, помимо перестраивания таблицы, делалась снова проверка - а вдруг еще какой-то таймер сработать должен?

В твоем коде это сделать довольно просто - принудительный вызов опять же _timer:update(). Минусы - чревато рекурсией, если таймеры таки сработают одновременно. Но учитывая реальне игровые условия, это маловероятно, а если и произойдет, то 1-3 одновременно (цифры с потолка, просто прикинула игровой процесс) максимум. Ну или для перестраховки ограничить количество рекурсий на один апдейт. Например, максимум 5 таймеров могут сработать. Остальные ждут следующего апдейта, судьба у них такая. :)

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   0 пользователей

    • Ни один зарегистрированный пользователь не просматривает эту страницу.
×
×
  • Создать...