- 1
def add_product_to_user(user, product_id,start_date=None, period=None, limit=True,end_date=None,rate=None,downrate=True):
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
−111
def add_product_to_user(user, product_id,start_date=None, period=None, limit=True,end_date=None,rate=None,downrate=True):
Шло время, система обрастала новыми фичами и необязательными параметрами.
Bart 05.03.2013 16:48 # +4
guest 22.03.2013 17:48 # −1
3.14159265 22.03.2013 18:11 # 0
Причина именно в этом: приучает людей передавать по всей системе 20 именованных параметров вместо того чтобы думать головой и заводить структуры (классы, кортежи, мапы, итд).
Тут же полезно вспомнить фпхацкил, где кол-во аргументов сводят к абсолютному минимуму.
guest 22.03.2013 18:24 # −1
Ясно, что в статических языках могут быть проблемы перекомпиляции (насколько я могу судить, опциональные параметры суть baked-in в callsite'е), но в динамических языках типа Питона это совершенно нормально, я считаю, т.к. основная причина использовать структуры вместо аргументов - борьба с собственным инструментом в лице компилятора/линкера/whatever (с другой стороны, в статич. языках это всё равно пол-решения: ну вот был у тебя конструктор с 3 параметрами. Внезапно нужно ещё 3 параметра. Что делать? Заводить специальную структуру? А ведь другой код надеется на конструктор без структуры. Может быть, вообще все методы и конструкторы должны принимать один аргумент в виде структуры изанчально? _А мало ли_? И т.д. И вот уже у нас не код, а over-engenieered говнокод-простыня)
Per se в принципе хорошая вещь.
>кортежи
Семантически набор аргументов в функцию и есть кортеж. А питоновский tuple и вовсе, IIRC, неименованный и позиционный, что есть источник большего числа багов.
>приучает людей ... вместо того чтобы думать головой
Если человек не может думать головой -- никто его ни к чему не приучит. Доказательство сему сей сайт.
3.14159265 22.03.2013 18:31 # −1
Полагаю парни из мса опытней нас с тобой будут. Всё правильно сделали.
Плюс сказывается убогость языка и отсутствие оператора with.
>Семантически набор аргументов в функцию и есть кортеж.
Правда с одним отличием.
>ну вот был у тебя конструктор с 3 параметрами.
Он уже плохо пах.
>Внезапно нужно ещё 3 параметра. Что делать? Заводить специальную структуру?
А потом по всей системе горы параметров, имена которые прибиты гвоздями к точке вызова.
>Заводить специальную структуру?
Она уже должна быть заведена. Добавить их туда.
>А ведь другой код надеется на конструктор без структуры.
Причем тут другой код?
guest 22.03.2013 18:44 # −1
Да ничё не правильно, они тупо вдохновилисб WinAPI-структурой STARTUPINFO. А WinAPI это Си, где именованных аргументов не вставишь.
>Плюс сказывается убогость языка
Какая такая убогость? Как иначе можно сделать в других языках?
>А потом по всей системе горы параметров, имена которые прибиты гвоздями к точке вызова.
А я про чё и говорил? Это плохо только в статич. языках, где ты борешься с собственным компилятором, а в динамич. вроде Питона это совсем не проблема, т.к. ничто нигде не прибито.
3.14159265 22.03.2013 18:54 # 0
В идеале, да.
В языках (тот же питон) с сахаром obj.b(other), который значит Object::b(obj,other) можно обойтись и одним. Частичное применение может несколько снижать производительность, потому 3 - оптимально, чтоб строить пары и тройки.
>а в динамич. вроде Питона это совсем не проблема
Чую когда-нибудь найдутся люди готовые заменить интерпретатор компиляцией. А без этого питон, при всей своей привлекательности - тормозное г.
3.14159265 22.03.2013 18:58 # 0
Да как угодно... Инициализаторы класса, with.
Просто стоит иногда выглядывать за пределы уютного шарпомирка.
guest 22.03.2013 19:05 # −1
Или я не понял, что ты пытаешься втереть.
3.14159265 22.03.2013 19:06 # 0
>>Инициализаторы класса. (FYI: так оно называется)
А вот дополнить свойствами после его создания он не умеет.
bormand 22.03.2013 20:00 # +3
Кошерная сишечка 99 тоже умеет в красивую инициализацию структур: Можно даже опустить часть полей, и они будут заполнены нулями.
guest 22.03.2013 22:49 # −1
3.14159265 22.03.2013 22:54 # +1
Более того в том же шарпике/яве конструктор отдельно, а инициализатор отдельно.
guest 22.03.2013 18:51 # −1
Кто в трезвом уме и памяти заводить по структуре на каждый метод?
3.14159265 22.03.2013 18:34 # 0
Удачи тебе. Бегать по проекту и везде добавлять эти 3 параметра.
А через год еще 5.
Гавно этот питон, раз даёт возможность так писать.
Я б вообще сделал язык с процедурами не больше 3-х аргументов.
И уровнями вложенности операторных скобок не больше 8.
И в операторе case запретил больше 30 параметров. Итд.
Короче, идеи где что ограничить брал бы с данного сайта.
guest 22.03.2013 18:45 # −1
>Гавно этот питон, раз даёт возможность так писать.
Зачем бегать добавлять 3 параметра, если они именованные и опциональные. Ты дурак?
3.14159265 22.03.2013 18:51 # 0
Да. Раз трачу на тебя время.
У тебя есть цепочка. Метод А передает пачку параметров методу Б, который передает часть из них методу C.
Ты решил дополнить А новыми параметрами. Это неизбежно тянет за собой чтоб А передал дополнительные параметры в Б, а тот в что-то в С.
Если в А передать структуру, то он передаст ссылку на неё в Б, а тот в С.
Код менять не надо. Только структуру.
guest 22.03.2013 19:14 # −1
А какова вероятность того, что А, Б и С принимают структуру одного типа в качестве аргумента? Близко к нулю.
Если мы дополняем А новыми параметрами, то мы в той же самой функции дополняем параметр и в Б. А дальше пересыл такого опциональногго аргумента уже как-то маловероятен, мне кажется, если это не конструктор с глубоким constructor chaining вверх по наследованию, но имхо, если нужно так много передавтаь данных вверх по наследованию, то автор точно делает что-то не так. Можно же просто переопределять виртуальные свойства.
Это как бы меньше кода, да, чем заводить по новой именнованной структуре на каждый метод
Алсо, IIRC Питон умеет трактовать опциаональные параметры как словарь, но я не помню как.
3.14159265 22.03.2013 19:19 # 0
>Близко к нулю.
Нет. Более того класс может реализовывать различные интерфейсы, подходя для A, Б и С.
Класс может содержать вложенную структуру, которая пойдет в Б, а из него в С.
> уже как-то маловероятен
Это не аргумент. Потому что в реальности всё строго наоборот.
>вверх по наследованию, но имхо, если нужно так много передавтаь данных вверх по наследованию
Ну ты же сам предлагаешь передавать в конструктор 100500 параметров. Вот и пойдет оно у тебя по наследованию.
Есть 2 способа композиции: наследование и обёртка (адаптер, декорация, итд).
В наследовании арументы идут по цепочке вверх.
В обертках и адаптерах цепочка из методов.
guest 22.03.2013 19:36 # −1
Ну это уже скорее философский вопрос "что есть один объект, а что есть два". Ясно что никто в здравом уме не будет передавать целый семантический объект в виде разбросанных по аргументам значений. С другой стороны вот например, есть у нас метод c именованными аргументами String.Compare(String str, int offset = 0, int count = -1, CultureInfo info = null).
Во многих случаях надо сравнивать всю строку (offset = 0, count = -1), в других случаях CultureInfo дефолтный. Довольно удобно определять только то, что нужно, через именованные аргументы. Неужели ты предлагаешь здесь создать сущность StringCompareArg? Ну нахуй.
>Ну ты же сам предлагаешь передавать в конструктор 100500 параметров. Вот и пойдет оно у тебя по наследованию.
А приватными для сего класса данные ну никак не могут быть да?
guest 22.03.2013 19:38 # −1
Да ещё и, блядь, какие-то интерфейсы сверху налепить. Может ещё через фабрику возвращать, да адаптеров сверху намутить?
Ебать.
3.14159265 22.03.2013 19:44 # 0
Я в данном месте считаю это излишеством, но во многих толковых либах (гуава) так и поступают.
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Joiner.html
Чтобы сделать join (там дохуя всяких аргументов) они порождают специальный объект Joiner где описано как надо джойнить.
Потому что можно один раз его породить. И использовать всюду.
И это правильно.
И пришли они к этому не сразу. А когда всё начало пухнуть и появляться новые фичи.
3.14159265 22.03.2013 19:52 # +1
И их преимущество перед передачей куч мусора в методы.
3.14159265 22.03.2013 19:41 # 0
Могут. Но когда наследуешься от конструктора с 20 аргументами их надо как-то передать наверх.
Но т.к. они приватные надо либо вызывать в конструкторе пачку сеттеров, либо эту пачку кидать наверх.
>есть у нас метод c именованными аргументами String.Compare(String str, int offset = 0, int count = -1, CultureInfo info = null)
Редкое исключение, из оперы: попытка написать метод который делает всё.
Который к тому же можно заменить регулярками (один аргумент).
guest 22.03.2013 22:54 # −1
Смысл опциональных аргументов как раз в том, что они опциональные, т.е. corner-cases, которые не всегда используются. Никто не должен передавать все аргументы. Если у родителя 20 аргументов, значит, он очень сильно genereal purpose, и текущий потомок использует только часть функционала, максимум аргументов 5 на практике. Это твоя проблема, что ты хочешь опциональные аргументы трактовать как неопциональные и таскать по всему коду.
>Редкое исключение, из оперы: попытка написать метод который делает всё.
Зато код не дублируется десять раз.
3.14159265 22.03.2013 23:00 # 0
Неправильно.
Наоборот. В других таких же all-in-one методах будут встречаться простые куски логики, которые дублируют уже существующие.
3.14159265 22.03.2013 23:01 # 0
Ну и какой же он общий? Мусорный он. Чем более абстрактный родитель, тем меньше у него должно быть этих полей.
>и текущий потомок использует только часть функционала, максимум аргументов 5 на практике.
Получается у наследника есть куча пустых полей, логически совсем не нужных ему. Это жутко и плохо.
>часть функционала
Эту часть можно вынести в отдельную структуру, если она общая. И сделать примесь, например.
Таким образом мы тихонько идём к моей концепции минимума аргументов.
guest 22.03.2013 23:11 # −1
Я имел в виду, что потомок реализует часть функционала. Прочий функционал, получается, реализуется родителем по дефолту. Часто встречаемый паттерн специализации.
3.14159265 22.03.2013 19:24 # 0
>> Метод А передает пачку параметров методу Б, который передает часть из них методу C.
Это и будет вложенная структура или реализация интерфейса.
>умеет трактовать опциаональные параметры как словарь,
>>заводить структуры (классы, кортежи, мапы, итд).
Вернулись к тому об чем я говорил. В питоне, по-моему, всё мапы и словари.
Просто сахара всякого больше чем в минималистичном js.
И продуманная стандартная либа. А так ничего особенного.
guest 22.03.2013 19:00 # −1
Да, и потом мы пишем транслятор чего-нибудь во что-нибудь с 31 элементом (напр., ISO-стандарт некоего байткода во внутреннюю оптимизированную IR-форму) и бамс... "Syntax error: 3.14159265 ne razreshil"
3.14159265 22.03.2013 19:03 # −1
В том же твоём сраном .NET, та же сраная сдудия не даёт.
И так детектятся клинические поциенты, которые с горелой жопой прибегают сюда жаловаться.
http://govnokod.ru/4260#comment47844
http://govnokod.ru/8627#comment122032
>Да, и потом мы пишем транслятор чего-нибудь во что-нибудь с 31 элементом
> "Syntax error: 3.14159265 ne razreshil"
Именно. И люди мне будут благодарны, что я мудаков криворуких отсеял на этапе компиляции.
guest 22.03.2013 19:26 # −1
Я .NET привёл в качестве примера один раз, хватит пиздеть.
Первая ссылка -- про вложенные if'ы. Это совсем не в кассу, так как switch-statement как раз разработан для эффективной обработки большого range'а входных данных, а 128 уровней вложенных if'ов это ограничение вследствие, видимо, плохо написанного парсера, надеющегося на рекурсию и пытающегося избежать stack overflow (та же история с с ограничением на количество вложенных меню в user32)
Вторая ссылка тоже говорит про "128 вложенных свичей ". Это опять мимо кассы. Причём тут количество case'ов в одном switch'e?
И 30 это слишком мало, я ещё понимаю хотя бы те же 128, ясно что бесконечности нигде не может быть.
3.14159265 22.03.2013 19:29 # 0
Лооол.
Ну-ка покажи мне практический код где было такое необходимо и у тебя реально используется более 128 ifов, или case.
Можно отдельным тредом.
>switch-statement как раз разработан для эффективной обработки большого range'а входных данных
А вот недавно же было.
http://govnokod.ru/12676
Эффектно.
guest 22.03.2013 19:51 # 0
Ясно что в таком таком примитивном случае это просто возврат свойства. Но если идёт, например, трансляция, где результат зависит от разного вида комбинаций нескольких decoupled сущностей, то case'а не избежать. В твоём же примере тупо возврат свойства, локального одному объекту.
>Ну-ка покажи мне практический код где было такое необходимо и у тебя реально используется
https://github.com/mono/mono/blob/master/mono/mini/mini-x86.c#L2481
И я не говорил, что 128 это круто. Я говорил, что твои 30 - слишком мало.
3.14159265 22.03.2013 19:57 # 0
Это же говно концентрированное.
Спасибо. Плюс.
3.14159265 22.03.2013 20:07 # 0
Большой свитч можно разбить на несколько меньших.
30 нормальным людям должно хватать.
А выше, может ты не знал, но есть такая вещь как полиморфизм. Я его не особо.
Но он эффективнее.
С коммандами x86 можно сделать это логически:
switch (type){
Case x86:
..
Case FPU:
..
Case SSE:
..
Case SSE2:
..
Case SSE3:
..
Case SSSE3:
..
Case SSE4
...
Case AVX
...
Case FMA
...
Case 3DNOW
...
}
guest 22.03.2013 21:52 # −1
В приведённом коде происходит трансляция IR-формы в опкоды целевого процессора. Какой нахуй "case SSE2"? IR-форма это и так абстракция, там нет SSE, потому что это фича Intel-процессоров. Ребята просто и незамысловато транслируют код одинаковым простым методом "по порядку" для разных процессоров, не вводя никакой overengeneered поебты. Он как раз более читаем и логичен для всех платформ, чем твоё ынтырпрайзное желание категоризировать чисто ради самой категоризации.
3.14159265 22.03.2013 21:58 # 0
Она будет работать быстрее чем огромный свитч и перебор тысячи комманд.
>Ребята просто и незамысловато транслируют код одинаковым простым методом "по порядку" для разных процессоров, не вводя никакой overengeneered поебты.
>не вводя никакой overengeneered поебты.
Да неужели? Такая незамысловатая портянка.
>Ну у нас теперь два уровня индирекции вместо одного, плюс ещё один enum.
Объясняю тебе олуху что с 30 ветками в свитче жить можно. Для этого надо объединять данные, структурировать их.
Привел пример как.
>Что дальше?
То что у тебя не будет тупого перебора вообще всего. А по типу комманды мы можем попасть на гораздо меньший диапазон комманд.
guest 22.03.2013 22:09 # −1
На 0.01%? Основанная логика генерации JIT-кода заключается в трансляции MSIL в IR, а не в IR => native , который представлен в обсуждаемом коде.
>То что у тебя не будет тупого перебора вообще всего.
С хуёв ли будет перебор? Если в энуме нет странных дыр, то Си сгенерирует статический jump-table (соотнесение опкода: if(i < MAX) goto jmptbl[i]; У тебя их будет два. Молодец.
Если ты имеешь в виду не алгоритмический перебор, а семантической, то опять же, ту же самую "проблему" решает адекватная группировка с небольшими комментариями.
>Объясняю тебе олуху что с 30 ветками в свитче жить можно
А я тебе объясняю олуху, что x86 FPU это 80 инструкций. Как они влезут в твой предел 30? Ещё одну индирекцию вставишь? И она ускорит моно каким-то образом аж на 0.001%?
3.14159265 22.03.2013 22:12 # 0
> что x86 FPU это 80 инструкций.
И среди них есть подгруппы. Арифметика, переносы, сдвиги, адреса.
3.14159265 22.03.2013 22:02 # 0
Да. Если потребуется. Со своими кучами именованных параметров ты не слышал о таких базовых вещах структура, дерево, список.
Поиск по дереву. Вместо тупого перебора.O (log(n)).
Ты же совсем ничего не знаешь, но уже считаешь себя умнее чем MS. Умнее чем люди, которые придумывали структуры данных и алгоритмы.
Или добавлю полиморфизм. 30 переборов обычно дольше.
guest 22.03.2013 22:25 # −1
Нет блядь, давайте создадим 30 классов с 10 адаптерами и 5 фабриками, чтобы алгоритм был куда быстрее, O (log(n))
Пиздец ты наркоман.
3.14159265 22.03.2013 22:26 # 0
А он точно у тебя линейный? А точно у тебя всё туда заинлайнится?
А когда ifdefы в серединке пишут, или какие команды отсутствуют в данном процессоре?
bormand 22.03.2013 22:35 # 0
Если веток мало - генерятся тупо if'ы.
Если почти все ветки разные и стоят плотно - генерится один jump table.
Если много одинаковых веток (дырка = много одинаковых дефолтов) то делается двухуровневая хреновина из index table и jump table.
Так что переборов там быть не должно, даже если полно дырок.
3.14159265 22.03.2013 22:38 # 0
Ну я примерно такое и предлагал сделать руками, явно.
В структурированом коде легче и удобней разбираться.
Судя по коду, автор - большой любитель свичей. Даже там где они не нужны.
mono_arch_fregname
guest 22.03.2013 22:44 # −1
3.14159265 22.03.2013 22:46 # 0
Делать работу по структурированию кода.
Чтоб оно читабельно было. Для людей.
Именно для этого, в первую очередь, нужны мои ограничения.
И правильно @wxvxw сказал. В кои-то веки абсолютно полностью с ним согласен.
Если б представленный код был сгенерирован - я бы еще понял.
guest 22.03.2013 23:04 # −1
Структурирование линейного трансляции? Может ты ещё для суммирования чисел от 1 до N три уровня абстракций введёшь?
3.14159265 22.03.2013 23:07 # 0
Оно либо должно быть логически упорядочено (если это делал человек и будет сопровождать человек).
Либо сгенерировано, если это тупой и простой список.
В обоих случаях switch на 200+ ветвей не нужен.
guest 22.03.2013 23:10 # −1
guest 22.03.2013 23:13 # −1
>Либо сгенерировано
Ага и генератор сам будет больше и тольще (и баговее), чем сама результирующая функция. Браво!
3.14159265 22.03.2013 22:43 # 0
У поциента запущенный свитчизм головного мозга.
guest 22.03.2013 23:01 # −1
guest 22.03.2013 22:40 # −1
>А когда ifdefы в серединке пишут, или какие команды отсутствуют в данном процессоре?
Значения для энумов генерируется автоматом, инкрементально. Если где-то есть ifdef, убирающий элемент перечисления, то компилятор просто переопредилит энум так, чтобы всё было всё равно sequential. Всю идиллию можно сломать, только если вручную написать OP_MYOPCODE = 1, но так никто в здравом уме не делает (если это не перечисление-флаг или не реализация публичного стандарта).
Это как, в стандартах не определено что такое "стек". Это может быть и вообще динамическая аллокация. Конечно можно задаваться вопросмом "а точно аллокация быстрая? а может быть мне лучше в статическую память писать?", но на практике это тупые вопросы.
3.14159265 25.03.2013 15:36 # +1
>Какой тупой копипаст?
Объясняю. Вам обоим.
Код представляет из себя вот такую портянку:
>x86_sse_alu_ps_reg_reg
Вынесение логики в методы - это уже оверхед.
>than many classes.
В сишке нет классов, уёбок. А полиморфизм - это идея. Идея таблицы с указателями на функции. По сути то же что делает свитч.
Прикол в том, что полезных данных этот свитч не несёт. Только унылые breakи - это уже оверхед.
И при правильной группировке можно задать:
вот для этого списка комманд нужно вызвать этот метод, для этого - этот.
Тогда от свитча можно избавится вовсе.
Кратко. Моя идея заключается в следующем:
Задаём массив соотвествия, который содержит полезную информацию и убираем большой свитч.
3.14159265 22.03.2013 22:23 # 0
Он не простой, а с ifdefами. И попытками заточек под конкретную архитектуру и набор комманд.
wvxvw 22.03.2013 20:10 # +1
guest 22.03.2013 21:55 # −1
wvxvw 22.03.2013 22:08 # +2
Такие вещи правильно разбивать на блоки, использовать какой-нибудь жаблон типа посетителя, например, который бы позволил разнести действия связанные с конкретными опкодами в файлы относящиеся к конкретному опкоду / группе опкодов. Хз. почему там свитч существует, возможно кто-то решил сэкономить процессорных такт угробив на этот кусок кода лучшие годы своей жизни. Идеология типичная для Си, когда даже при возможности запилить шаблон / сгенерировать, люди все равно будут врукопашную все оптимизировать, разворачивать циклы, инлайнить вручную и т.п...
bormand 22.03.2013 22:20 # 0
Иногда это действительно нужно ;) Но не так часто.
guest 22.03.2013 22:23 # −1
3.14159265 22.03.2013 22:25 # 0
В моем языке будут запрещены чрезвычайно длинные процедуры и модули.
Обязательно.
bormand 22.03.2013 22:31 # +1
Тогда уж и длинные строки.
wvxvw 22.03.2013 22:31 # +1
Но, нужно обратить внимание, что тут не все так просто, есть по дороге какие-то исключения, ветвления и т.п. на которых нужно 1. сконцентрировать внимание читающего (а не похоронить где-то в общей куче), 2. их нужно сгруппировать так, чтобы их было проще найти, в зависимости от возможной поставленной задачи (например, нужно найти все инструкции, которые будут актинвы при каком-то выбранном условии). Шаблон типа посетителя как раз таки и поможет это сделать, т.как вместо того, чтобы листать огромный свитч и искать в нем необходимую инструкцию, можно будет открыть файл в котором она предположительно находится, и максимум с двух-трех попыток угадать - это все равно избавит от необходимости листать весь свитч.
guest 22.03.2013 23:00 # −1