Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 9 из 9
  1. #1
    Аватар для Elrmrnt-Kritik
    Пользователь

    Статус
    Оффлайн
    Регистрация
    05.11.2017
    Сообщений
    136
    Репутация:
    10 ±

    Вынесение проверок в функции

    Сейчас пересматривал свои последние системы и столкнулся с такой проблемой, которую я же сам и создал. Зачастую у меня одна и та же проверка есть и в функции, и перед тем, как вызывается эта функция. Где ее лучше оставить, а где все-таки лучше снести?
    Пример кода:
    1. #define DLG DialogResponse
    2. enum
    3. {
    4. DLG_ENTER_PASSWORD,
    5. }
    6. static const
    7. MIN_LENGTH_PASSWORD = 6,
    8. MAX_LENGTH_PASSWORD = 16;
    9.  
    10. // неважно где
    11. ShowPlayerDialog(playerid, DLG_ENTER_PASSWORD, DIALOG_STYLE_PASSWORD, "Текст", "Введите пароль", "Ок", "Закрыть");
    12. DLG:DLG_ENTER_PASSWORD(playerid, response, listitem, inputtext[])
    13. {
    14. if(!response)
    15. return 1;
    16.  
    17. new length = strlen(inputtext);
    18. if(!(MIN_LENGTH_PASSWORD <= length <= MAX_LENGTH_PASSWORD))
    19. return 1;
    20. else if(!IsValidPassword(inputtext))
    21. return 1;
    22. // неважно что
    23. return 1;
    24. }
    25. stock IsValidPassword(password[])
    26. {
    27. new length = strlen(password);
    28. if(!(MIN_LENGTH_PASSWORD <= length <= MAX_LENGTH_PASSWORD))
    29. return 0;
    30.  
    31. new string[33+(-2+2)*2+1] = "|[A-Za-z0-9#$-_+=;:@!?]{%d,%d}|";
    32. format(string, sizeof string, string, MIN_LENGTH_PASSWORD, MAX_LENGTH_PASSWORD);
    33. return regex_match(password, string);
    34. }


    Попутно так еще одну вещь хотел бы уточнить все по этому же коду. Понятно, что в моей функции IsValidPassword можно было бы обойтись без формата, если бы MIN_LENGTH_PASSWORD и MAX_LENGTH_PASSWORD были макросами. Но я решил это сделать константами. Вообще сейчас все лимиты и значения стараюсь указывать через константы. Что думаете по этому поводу? Лучше переводить на макросы и забыть про format в таких ситуациях?

    - - - Добавлено - - -

    Еще вспомнил, что хотел узнать уже давно, но все забывал. Если нужно, пожалуйста, перенесите в отдельную тему. Как вы смотрите на моды, написанные исключительно на C++? Ведь в них идет постоянный вызов нативных функций, что по идее плохо влияет на скорость работы. Но в то же время работа всех функций в C++ идет быстрее. Компенсируется ли быстрота работы кода в C++ вызовом нативных функций из мода?

  2. #2
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от Elrmrnt-Kritik Посмотреть сообщение
    Где ее лучше оставить, а где все-таки лучше снести?
    Оставляй проверку везде, где результат работы функции зависит от значения переменной, которое проверяется в условии.
    Если тебя пугает то, что на выполнение условия тратится время, то эти траты ничтожно малы в сравнении с возможными ошибками и багами из-за невалидных данных. А если вдруг какая-то из подобных функций вызывается, например, в цикле или таймере, где действительно важно экономить каждую миллисекунду, лучше просто продублируй нужный код из функции внутри этого таймера/цикла, убрав ненужные проверки. Но убирать проверки внутри самих функций я бы не советовал. Может аукнуться рано или поздно.


    Цитата Сообщение от Elrmrnt-Kritik Посмотреть сообщение
    Попутно так еще одну вещь хотел бы уточнить все по этому же коду. Понятно, что в моей функции IsValidPassword можно было бы обойтись без формата, если бы MIN_LENGTH_PASSWORD и MAX_LENGTH_PASSWORD были макросами. Но я решил это сделать константами. Вообще сейчас все лимиты и значения стараюсь указывать через константы. Что думаете по этому поводу? Лучше переводить на макросы и забыть про format в таких ситуациях?
    Как вариант, просто делай макрос + константу, а-ля
    PHP код:
    #define MSG_MIN_LENGTH_PASSWORD 64
    const MIN_LENGTH_PASSWORD MSG_MIN_LENGTH_PASSWORD
    И уже там, где нужно форматировать текст, используй макрос, а в условиях используй константу.
    Правда не уверен, что в этом будет большой смысл, если честно.

    Можно ещё придумать какой-нибудь такой костыль с единоразовым форматированием:
    PHP код:
    static test_message[27+2+1];
    if(
    isnull(test_message))
    {
        
    format(test_messagesizeof(test_message), "Минимальный размер пароля: %d"MIN_LENGTH_PASSWORD);
    }
    SendClientMessage(playerid, -1test_message); 
    Только стоит понимать, что такой вариант скушает в два раза больше памяти, так как помимо того, что нужно выделить место под массив, так же и строка в format должна где-то хранится до того, как попадёт в наш массив. В итоге получится, что она продублируется в памяти (один раз без значения макроса, а второй раз, находясь в массиве, со значением).
    Это, конечно, не критично, ибо таких ситуаций в SA-MP скриптинге полно. Просто рассказываю, что и у этого варианта есть свои "минусы".

    Цитата Сообщение от Elrmrnt-Kritik Посмотреть сообщение
    Еще вспомнил, что хотел узнать уже давно, но все забывал. Если нужно, пожалуйста, перенесите в отдельную тему. Как вы смотрите на моды, написанные исключительно на C++? Ведь в них идет постоянный вызов нативных функций, что по идее плохо влияет на скорость работы. Но в то же время работа всех функций в C++ идет быстрее. Компенсируется ли быстрота работы кода в C++ вызовом нативных функций из мода?
    Само по себе использование С++, Assembler, Lua, Pawn или какого-либо другого ЯП не даёт ничего. Говнокод можно писать на любом языке. Так же, как и для того, чтоб писать хороший код, нужно иметь достаточно знаний.
    Ну а вообще, лично я считаю это бессмысленным извращением в любом случае. SA-MP прекрасно работает и с модификациями, написанными на Pawn, поэтому даже если представить, что мод на каком-то другом языке будет работать быстрее, от этого толку будет не очень много.
    Последний раз редактировалось DeimoS; 01.06.2018 в 23:11.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  3. Пользователь сказал cпасибо:
    Elrmrnt-Kritik (01.06.2018)
  4. #3
    Аватар для Elrmrnt-Kritik
    Пользователь

    Статус
    Оффлайн
    Регистрация
    05.11.2017
    Сообщений
    136
    Репутация:
    10 ±
    Только вот с памятью не сообразил. Понятно, что сам текст попадет в сегмент данных, с этим вроде как уже давно все уяснил. Также понятно, что выделится место в памяти (static test_message[27+2+1];). Ведь это и есть двойной расход памяти? А как же такая ситуация:


    1. new string[27+2+1];
    2. format(string, sizeof string, "Минимальный размер поля: %d", MIN_LENGTH_PASSWORD);




    По сути тоже самое: содержимое текста попадает в сегмент данных, только вот "ликвидируется" переменная string. (я смотрел не так давно лекцию институтскую насчет памяти, где рассказывалось про то, как система понимает начало и конец определенной переменной, как ее добавляет и удаляет, про структурки MCB). Так вот, ко второму варианту нет же придирок. А в чем тогда беда собственно? Что костыль постом выше лишь не "удаляет" эту переменную из памяти?
    (а как вообще правильно назвать "удаление" переменной из памяти?)
    Последний раз редактировалось Elrmrnt-Kritik; 02.06.2018 в 00:00.

  5. #4
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от Elrmrnt-Kritik Посмотреть сообщение
    Только вот с памятью не сообразил. Понятно, что сам текст попадет в сегмент данных, с этим вроде как уже давно все уяснил. Также понятно, что выделится место в памяти (static test_message[27+2+1];). Ведь это и есть двойной расход памяти?
    Да, это и будет двойной расход (и массив, и текст "раздуют" сегмент данных, который не изменяется во время работы сервера стандартными средставми).

    Цитата Сообщение от Elrmrnt-Kritik Посмотреть сообщение
    А как же такая ситуация:


    1. new string[27+2+1];
    2. format(string, sizeof string, "Минимальный размер поля: %d", MIN_LENGTH_PASSWORD);




    По сути тоже самое: содержимое текста попадает в сегмент данных, только вот "ликвидируется" переменная string.
    Нет, не то же самое. Тут массив будет создан в стэке и после обработки блока кода, в котором создан массив, память, зарезервированная этим массивом, станет доступна для перезаписи. Соответственно, двойного потребления памяти уже не будет, но...

    Цитата Сообщение от Elrmrnt-Kritik Посмотреть сообщение
    А в чем тогда беда собственно? Что костыль постом выше лишь не "удаляет" эту переменную из памяти?
    (а как вообще правильно назвать "удаление" переменной из памяти?)
    ...беда как раз в постоянном "насиловании" стэка. То бишь, каждый раз, когда будет вызываться этот код, часть стэка сначала будет резервироваться для массива, а потом в этот массив будет заносится текст из сегмента данных. Это так же не смертельно, но и бессмысленно с учётом того, что строка не будет изменятся во время работы сервера.

    Самым идеальным вариантом будет либо полный отказ от констант в пользу макросов, либо макрос + константа. На деле оба варианта идентичны, ибо и макрос, и константа после компиляции превратятся в то число, которое присвоено этим макросу/константе (макрос "развернётся" во время работы препроцессора, а константы "развернёт" компилятор). Разница тут лишь в читаемости кода (ну дополнительную информацию нужно будет помнить. Хотя если проработать нормальную систему префиксов для таких макросов, то проблем быть не должно)
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  6. Пользователь сказал cпасибо:
    Elrmrnt-Kritik (02.06.2018)
  7. #5
    Аватар для Elrmrnt-Kritik
    Пользователь

    Статус
    Оффлайн
    Регистрация
    05.11.2017
    Сообщений
    136
    Репутация:
    10 ±
    Хотел уже попросить закрыть тему, только еще одно предложение заметил: "константа после компиляции превратятся в то число, которое присвоено этим макросу/константе". Константа же попадет в сегмент данных и будет там сидеть, ее адрес везде будет использоваться. А макрос засунет в десятки мест одно и то же число и будет в сегменте десятки мест под это число. Или для чисел такое неактуально?

  8. #6
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от Elrmrnt-Kritik Посмотреть сообщение
    Константа же попадет в сегмент данных и будет там сидеть, ее адрес везде будет использоваться.
    В секцию данных попадают глобальные переменные, а у констант значения подставляются прямиком в код (т.е. в каждую инструкцию AMX, в которой они используются).
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  9. #7
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от Elrmrnt-Kritik Посмотреть сообщение
    Константа же попадет в сегмент данных и будет там сидеть, ее адрес везде будет использоваться. А макрос засунет в десятки мест одно и то же число и будет в сегменте десятки мест под это число. Или для чисел такое неактуально?
    Дополню ответ выше, дабы было понятнее:
    1. const name = 12;
    2. new const name = 12;
    3. static const name = 12;
    4. static const name[MAX_PLAYER_NAME] = "DeimoS";

    Константой тут является лишь код на первой строке. Всё остальное - переменная с флагом "read-only".
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  10. Пользователь сказал cпасибо:
    Elrmrnt-Kritik (16.06.2018)
  11. #8
    Аватар для Elrmrnt-Kritik
    Пользователь

    Статус
    Оффлайн
    Регистрация
    05.11.2017
    Сообщений
    136
    Репутация:
    10 ±
    А, ну, то есть только числа подставляются в итоговый вариант, если присутствует модификатор const. А в остальных (трех последних) случаях значения переменных с флагом "read-only" будут заменяться адресами к ячейкам? На значение этой переменной соответственно.

  12. #9
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    PHP код:
    const name 12
    Будет обрабатываться практически так же, как обычный макрос. Я тебе в другой твоей теме расписывал всё на этот счёт.
    Остальные случаи обрабатываются так же, как обрабатываются переменные (ибо это и есть переменные)
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  13. Пользователь сказал cпасибо:
    Elrmrnt-Kritik (16.06.2018)
 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •