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

Курилка программистов


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

В твоём же варианте все условия изолированы.

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

Изменено пользователем Serge!
Ссылка на комментарий

Не покатит, поскольку такая матрёшка из условий почти всегда подразумевает, что какие-то из условий невозможно вычислить, если не выполняются какое-то из предыдущих

Ты имеешь ввиду лишние вызовы?

for i = 1, 65535 do
if alife():object(i) and level.object_by_id(i) and level.object_by_id(i):is_stalker() then ... end
end

смущает что два раза вызвал object_by_id?

Изменено пользователем RayTwitty
Ссылка на комментарий

@RayTwitty,

Смущает? Да за такой код по рукам бить надо. У тебя в цикле перебора всего диапазона id три раза вызываются функции, которые сами по себе перебирают все объекты (вообще все или на уровне). Причём третий вызов и вовсе не нужен, и стоит только затем, чтобы что-то доказать.

 

Впрочем, речь то не об этом. Ты опять себе упростил задачу. Я же ранее явно в примере кода указывал "долго вычисляется условие такое то". Ключевое слово "долго", т.е. в несколько строчек. И не упакуешь ты тогда всё условие в одно выражение.


 

 

Но я ведь могу в эти функции передать

Да можно конечно. Вот только ответь на простой вопрос: решает ли это ту задачу, с которой я начал - сделать код проще и понятнее? Просто погляди критичным взглядом и сравни три варианта: исходную матрёшку, твой вариант, вариант линейной записи.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

У тебя в цикле перебора всего диапазона id три раза вызываются функции, которые сами по себе перебирают все объекты (вообще все или на уровне).

Кстати в JavaScript присваивание переменных возвращает собственно присвоенное значение. Это повсеместно используется для одновременной (в 1 строке) указания глобальной и локальной переменных. Например "var generator = App.tools.QueryGenerator = new MyQueryGenerator(param1, param2)".

Такое же можно использовать в любых ситуациях, в том числе и в условном ветвлении, но это очень запутывает, однако я иногда такое применял + делал коммент.

ТЧ 1.0004. SAP и Trans mod

github

Ссылка на комментарий

 

 

Кстати в JavaScript присваивание переменных возвращает собственно присвоенное значение.

Украдено из СИ, как и общий синтаксис.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

У тебя в цикле перебора всего диапазона id три раза вызываются функции, которые сами по себе перебирают все объекты

Впрочем, речь то не об этом.

Речь не о производительности, да. Понятное дело, что три цикла - это ахтунг, но код нерабочим от этого не стал.

 

Я же ранее явно в примере кода указывал "долго вычисляется условие такое то"

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

 

 

Обычно, я "долгие вычисления" делаю где-то в другом месте, а не внутри общей функции

Вроде уже несколько раз объяснял. Совершенно типичная ситуация, что ты не можешь вычислить условие 2 до тех пор, пока не выполнено условие 1, а условие 3 до тех пор, пока не выполнено условие 2 и т.д. Неужели это настолько непонятно? Ты не можешь сделать это заранее. И не будешь же ты выносить в функцию несколько строчек специально для того, чтобы где-то в одном месте соединить несколько условий в одну строку. Функции не для этого создают, да и лишено это смысла, поскольку не добавит коду ни понятности ни эффективности.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

Совершенно типичная ситуация, что ты не можешь вычислить условие 2 до тех пор, пока не выполнено условие 1, а условие 3 до тех пор, пока не выполнено условие 2 и т.д. Неужели это настолько непонятно?

По законам мат. логики оно итак не будет выполняться:

a & b & c
Если a = 0, то дальше даже смотреть не будет, соответственно там может быть все что угодно.

 

З.Ы. впрочем, есть ли конкретный код, в скриптах ОГСЕ например? Они у меня в наличии.

Изменено пользователем RayTwitty
Ссылка на комментарий

По законам мат. логики оно итак не будет выполняться: a & b & c

 

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

https://ru.wikipedia.org/wiki/Математическая_логика

Я бы и сам не рискнул произносить это название, поскольку не математик ни разу. Вообще говоря, то, что мы в бытовом смысле понимаем под логикой, в мат.логике являетя весьма маленьким разделом под названием "Логика высказываний"

https://ru.wikipedia.org/wiki/Логика_высказываний

 

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

 

Разумеется, если можно безболезненно, без потери читаемости и эффективности кода, соединить несколько условий в одно, то в этом действительно часто есть смысл. Хотя и тогда я иногда всё равно разбиваю условия на группы уже по смысловым соображениям или по соображениям отладки.

 

Но я то говорил об общем случае. Если выражении выше условие "b" вычисляется, во-первых, при условии истинности условия "a", а, во-вторых, на основе данных, которые вообще появляются только после (и вследствие) вычисления условия "a", то тогда в попытке соединить всё в одну строку имеем проблемы.

Для начала, если условие вычисляется в несколько строк. Единственным выходом является только заключить всё вычисление выражения в функцию, что не есть хорошо. Функция может получиться сугубо одноразовая (что само по себе лишает её смысла), а кроме того нужно туда ещё передать данные от вычисления предыдущего условия. И далее, здесь мы нарываемся на побочные эффекты языка, поскольку большинство языков не гарантируют последовательность вычисления компонент выражения.

Вот уже эти два соображения, многострочное вычисление выражения и зависимость условий, уже вынуждают отказываться от объединения выражений в одну строку. А тут кстати упоминали ещё и вариант с веткой else.

Вот тот-же самый код матрёшкой, но уже с альтернативными ветками.

 

 

function fff()
    if cond1 then
        ... -- долго вычисляем cond2
        local cond2 = ...
        if cond2 then
            ... -- долго вычисляем cond3
            local cond3 = ...
            if cond3 then
                --do_something
            else
                -- сделать что-то, если не сработало условие 3
            end
        else
            -- сделать что-то, если не сработало условие 2
        end
    else
        -- сделать что-то, если не сработало условие 1
    end
end

 

 

И опять линейный вариант смотрится куда как более читаемо.

 

 

function fff()
    if not cond1 then
        -- сделать что-то, если не сработало условие 1
        return
    end
    ... -- долго вычисляем cond2
    local cond2 = ...
    if not cond2 then
        -- сделать что-то, если не сработало условие 2
        return
    end
    ... -- долго вычисляем cond3
    local cond3 = ...
    if not cond3 then
        -- сделать что-то, если не сработало условие 3
    end
    --do_something
end

 

 

 

А здесь можно ещё упомянуть, что очень часто эти условия на самом деле являются затычками. Особенно тяжело с этим в практике модостроения в силу понятной низкой дисциплины большинства скриптёров. Т.е. очень часто вот такая конструкция в функции:

if not cond1 then
    return
end

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

 

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

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

@Malandrinus, во-первых, я буду поминать те вещи, которые считаю нужным; во-вторых, не надо иметь семи пядей во лбу чтобы знать 0 & .. & .. = 0, поэтому твои линки тут неуместны.

 

 

 


В этом аппарате нет никаких указаний насчёт обязательности/необходимости вычисления входящих в выражение условий.

В тех языках, которые я подразумевал (и которые скорее всего подразумевали другие), это свойство прекрасно работает.

 


Функция может получиться сугубо одноразовая (что само по себе лишает её смысла)

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

 


А тут кстати упоминали ещё и вариант с веткой else.

Я и упоминал, причем сразу сказал, что да, в этом случае условие придется записывать в несколько if-ов.

 

Если вернуться к изначальному вопросу:

 


Есть ли какие-то мысли по этому поводу?

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

 

Думаю, я ответил на вопрос.

 

З.Ы. забыл написать - наверняка воспринимаемость также зависит от монитора - лесенку удобно рассматривать на 21:9))

Изменено пользователем Black Hawk
Объединение постов.
Ссылка на комментарий

я буду поминать те вещи, которые считаю нужным

твои линки тут неуместны.

=) Да кто же тебя остановит? Просто несколько забавно видеть упоминание мат.логики для красного словца.

 

В тех языках, которые я подразумевал (и которые скорее всего подразумевали другие), это свойство прекрасно работает.

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

 

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

Завести функцию "про запас", только чтобы выделить несколько строк? Ну ок. Хотя при чём здесь тогда читаемость алгоритма?

 

лесенку удобно рассматривать на 21:9

Береги глаза смолоду, пригодятся позже. Кроме того, я уже пытался ранее объяснить, в чём проблема с матрёшкой. Здесь не в геометрии дело. На её разбор требуется больше усилий, больше краткосрочной памяти, больше времени в итоге. Это неважно, умный человек или нет. На более сложную задачу в любом случае потребуется больше времени. Не жалко времени?

 

Вот кстати про монитор. Не сильно то помогает ширина монитора. Скорее помогает высота, а сейчас практически вымерли мониторы 3х4 с оптимальной для программирования высотой. В итоге широкий монитор 24" примерно настолько же удобен для программирования, как старый 19".

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

Просто несколько забавно видеть упоминание мат.логики для красного словца.

Тут до меня этих "красных словцов" сказали столько, что я бы постеснялся об этом говорить :D

 

Ты полностью проигнорировал сказанное

Я уже давно попросил привести какой-нибудь пример из реального кода, в тех же скриптах.

 

А что касается "реализации аппарата логики" - там где я работаю, он полностью соответствует моему пониманию:

local a = false
if a and print("first") then
end
print("two")
 

Завести функцию "про запас", только чтобы выделить несколько строк?

Не только - я там написал ещё для чего.

 

Береги глаза смолоду

Это зависит не от соотношения сторон монитора, а от многих других параметров) Изменено пользователем RayTwitty
Ссылка на комментарий
Вот только ответь на простой вопрос: решает ли это ту задачу, с которой я начал

нет, поскольку такое просто невозможно. Объясню почему я так думаю.

Задачи, как таковой и не было поставлено изначально. Была некая схема и некий весьма общий вопрос. При этом не было оговорено никаких условий, а "что же считать правильным"?. По мере поступления предложений, схема начинала изменяться и начинали возникать новые вопросы и меняться критерии оценки предложенных решений. Я же всегда привык решать проблемы "по мере их поступления" и никогда впрок. Ваши же схемы, на мой субъективный взгляд, выдаются по принципу "два пишем, три на ум пошло". Я в такие игры не играю, т.к. тоже дорожу своим временем.

Поэтому, после перехода на третий круг, я бросил это занятие. Если есть желание продолжения коллективного поиска оптимального решения, то (повторяя фразу из одного известного фильма) "огласите весь список, пожалуйста".

Изменено пользователем Serge!
Ссылка на комментарий

Скорее помогает высота, а сейчас практически вымерли мониторы 3х4 с оптимальной для программирования высотой. В итоге широкий монитор 24" примерно настолько же удобен для программирования, как старый 19".

Так это, переверни его :D
  • Нравится 3

ТЧ 1.0004. SAP и Trans mod

github

Ссылка на комментарий
Так это, переверни его

а вот это зря. В этом вопросе я с Malandrinus согласен на все 200%. Широкоформатники хороши для просмотра видео, но никак не для тех, кто занимается работой (иногда правда для верстки бывает удобно, но и то не всегда). У меня дома 4 монитора 3х4 и только 1 широкий (у внука), а за новый ноут с квадратным монитором пришлось даже переплачивать. Редкость это теперь, всем больше мультики приятнее смотреть, чем комфортно работать

Изменено пользователем Serge!
Ссылка на комментарий

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

Ссылка на комментарий

Мужики, вы всегда такие серьезные?

Соседу когда присылают всякие *нечитаемые* портянки, то он так делает. Реально удобнее :)

ТЧ 1.0004. SAP и Trans mod

github

Ссылка на комментарий
Мужики, вы всегда такие серьезные?Соседу когда присылают всякие *нечитаемые* портянки, то он так делает. Реально удобнее

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

Изменено пользователем Serge!
Ссылка на комментарий

Задачи, как таковой и не было поставлено изначально. Была некая схема и некий весьма общий вопрос. При этом не было оговорено никаких условий, а "что же считать правильным"?

 

ок. Попробую обобщить. Получилось многословно, так что смотри под спойлером. В сущности, ничего нового я там не написал, всё давно было сказано в разных правильных книгах.

 

 

 

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

 

Общие задачи при написании программы

Когда пишем программу, то надо: потратить на написание как можно меньше времени, сделать код как можно эффективнее (в смысле быстрее) и как можно надёжнее (т.е. чтобы работал без сбоев). Думаю, это не нуждается в обосновании.

 

Скорость (Эффективность)

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

 

Затраты на написание и надёжность

Остаются только два важных вопроса: время написания и надёжность программы. Хочу здесь уточнить кое-что. Время написания - это не просто время, нужное на то, чтобы надолбать на клавиатуре выбранный алгоритм (обозначим его Т0). Так не бывает на практике, поскольку нужно время на отладку, т.е. исправление ошибок. Причём в целом всё это время выходит гораздо больше, чем Т0, зачастую во много раз больше. Отсутствие сбоев - тоже вещь неоднозначная. Это не обязательно отсутствие ошибок, но также и наличие затычек на имеющиеся косяки. В целом можно сказать, что меньшее время написания и надёжность кода друг другу противоречат. Вполне очевидно, что на более надёжную программу нужно больше времени.

 

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

 

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

 

Причины ошибок

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

 

Пути борьбы со сложностью

Что же остаётся программисту? Ну во первых конечно выбор для работы всего, что способно сократить нам сложность. Язык обычно навязан соображениями эффективности, но и здесь вопрос не закрыт полностью. Ассемблер или С/С++? Ассемблер - это чудовищное увеличение сложности и далеко не пропорциональное ему повышение скорости. Какие-то некритичные по скорости задачи можно решить в языке ещё более высокого уровня, чем С/С++? Значит разбиваем программу на части и реализуем по отдельности на разных  языках. Но это конечно не применимо к модостроению, где всё уже решено за нас.

 

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

 

Способы борьбы с внесёнными ошибками

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

 

Что делают неправильно

И наконец. Что является вредным и неправильным в свете сказанного?

Первое - трюкачество любого рода. Тут всё просто. Трюкачество по определению повышает сложность кода и значит безусловно вредно.

Крайне вредна ненужная бравада своей способностью написать и понять сложный и запутанный код. Опять же понятно, что это ведёт к трюкачествую и также к нежеланию комментировать.

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

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

 

 

 

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

 

 

  • Спасибо 1
  • Нравится 1
  • Полезно 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

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