LINUX.ORG.RU

Группа разработчиков Scala получила грант Евросоюза

 , , ,


1

4

Группа разработчиков языка Scala получила грант Евросоюза, выиграв конкурс языков для параллельного программирования. Разработчики получат в течение следующих 5 лет на развитие своего детища 2,3млн €.

Scala — язык программирования для платформы JVM, сочетающий возможности объектно-ориентированного и функционального программирования. Scala был разработан в лаборатории швейцарского ВУЗ’а EFPL.

>>> Подробности

★★★★★

Проверено: maxcom ()

Ответ на: комментарий от eao197

>Этот экземпляр будет убираться GC сразу после завершения doLogin

Ты вообще понял о чем я сказал? При чем тут gc? GC в конце концов соберет все. У тебя класс с состоянием.

Какой чужой системе?


Чужой системе автентикации - ты читал вообще то что делается если схема не петровка? runtime.exec!

То, что я ключевое слово private не поставил для класса/метода, это да.


a) приватность работает только для внешних классов. Ты говоришь что:

Класс KnownUserLoginHandler будет приватным для класса, в котором живет метод login


Все модификаторы видимости ушли за слонами на север.

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

c) Методы :
handleUnknownUserLogin
handleInactiveUserLogin
....
и тому подобные могут быть вызваны кем угодно и когда угодно.

Метод handleInactiveUserLogin не несет себе проверки неактивности юзера. Следовательно он легко нарушает инвариант - может быть вызван к любому юзеру. Так что давай начинай вставлять контракты. Тебе надо запретить недопустимый вызовы:
* new KnownUserLoginHandler - если хоть один параметр конструктора null
* handleUnknownUserLogin - если юзер известен или автентикация была осуществлена
* handleInactiveUserLogin - если юзер активен или автентикация была осуществлена
* handlePetrivkaAuthSchemeLogin - если схема не петровка или юзер неактивен, или автентикация уже была осуществлена
* handleUsualAuthSchemeLogin - если схема петровка или юзер неактивен, или автентикация уже была осуществлена
* setupSuccessfulAuthResult - если автентикация не была осуществлена.

Я не вижу что иначе помешает твой класс использовать неверно.

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

У него неизменяемое состояние и все методы handle* приватные.


Да ты вообще можешьсделать main программы приватным и сказать что проект на два гигабайта венсь из себя приватный.

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

r ★★★★★ ()
Ответ на: комментарий от eao197

Короче ты работающий железобетонный код который нельзя было вызвать неправильно превратил в огромную банку с потенциальными червями и багами начиная от перерачи сенситивной инфы во чужие системы и впусканием юзеров без всяких проверок и заканчивая неправильной работой.

Отрефакторил называется.

r ★★★★★ ()
Ответ на: комментарий от eao197

>У него неизменяемое состояние и все методы handle* приватные. Так что наезд мимо кассы.

К стати боллшое количество приватных методов - всеми признанный code smell. обозначает что класс занимается не своей работой. Если у тебя на 1 публичный метод приходится 4 приватных - значит класс делает то что делать не должен, и типичный рефакторинг для такого случая - инвариантный вынос логики приватных методов в отдельный клас где они будут публичными.

Ну а методы которые на внешнем глобальном инвариантном состоянии могут быть вызваны с ошибками - это вообще звездец.

r ★★★★★ ()
Ответ на: комментарий от eao197

Во-первых, настолько сильно я чужой код рефакторить не собирался :)

а во сколько (десятков?) раз он вырастет после сильного рефакторинга?

Во-вторых, каждый отдельный метод содержит их намного меньше :)

за счет того, что методов больше — так каждый может

Не только можно, а и нужно. Поскольку если base вдруг оказывается нечетным, а T это int/long, то при последующем чтении из этого адреса, например, на SPARC-ах, можно отхватить какой-то SIG* (уже не помню какой именно, давно дело было). А вот calculateAddress вполне может данную ситуацию обрабатывать...

... ничем не хуже вызова функции

еще повтрою, что речь идет именно о функциях однократного использования

кстати, обычно стоит коммент либо в виде коммента, либо в виде названия переменной

int calculated_аddress = base+offset*sizeof(T)

когда это становится чуть сложнее, то требуется where

а вот к коду

AccessStorage.access.auth_configs.find(_.key == user.authScheme) match {
   ....
}
я думаю претензии можно предъявить

именно, скорее всего, это проектировалось сверху вниз, и даже если автор не записал «validate auth scheme», то он точно это подумал, и в результате имеем *утерянную* инфу; чтобы она не терялась, пишем

val validatedAuthScheme = AccessStorage.access.auth_configs.find(_.key == user.authScheme)

validatedAuthScheme match {
   ....
}

но делать для этого отдельную функцию — явный канцелярит

... и вообще, валидация должна была бы не давать возможность внутри match обратиться к user.authScheme

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от r

Ты вообще понял о чем я сказал? При чем тут gc? GC в конце концов соберет все. У тебя класс с состоянием.

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

И да, класс с состоянием. Что тут такого? Оно где-нибудь изменяется? Оно сказывается еще на чем-то?

Чужой системе автентикации - ты читал вообще то что делается если схема не петровка? runtime.exec!

И что? У тебя дергается runtime.exec и у меня. В тех же самых ситуациях. Только у тебя exec дергается прямо из login, у меня из handleUsualAuthSchemeLogin, но в handleUsualAuthSchemeLogin можно будет попасть только из login. Число шагов просто увеличено, но сами шаги остались теже самые.

a) приватность работает только для внешних классов. Ты говоришь что:

Класс KnownUserLoginHandler будет приватным для класса, в котором живет метод login


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

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

Внутри реализации вашего исходного login можно звать любые методы, включая неправильную последовательность. Стоит какому-нибудь разработчику добавить что-нибудь перед вашим первым if-ом и все! Куда денется защина от null-евого login или password?

Я не вижу что иначе помешает твой класс использовать неверно.

Да, если в Scala нет возможности ограничить контекст использования какого-то вспомогательного класса, то ничего не помешает.

Не говоря уж о прочих рефлекшенах.

Ну что тут сказать? Если целью исходного кода была, в том числе, и защита от рефлекшена, то тут я ничего не могу возразить. Цель достигнута.

eao197 ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

>чтобы она не терялась, пишем

А в чем разница? Если че - auth_configs - это просто список. Я не понимаю что такое validated. У юзера есть параметр как его надо автентицировать - название схемы. Гдето есть конфиг который загружается в AccessStorage.access.auth_configs. Этот код просто ищет схему соответствующую user.authScheme. Грубо говоря это мап. Просто там злобный JSON который мапов не умеет. Схема нашлась - автентицируем, не нашлась пишем - фигня василий ваныйч у вас написана в схеме автентикации.

r ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

а во сколько (десятков?) раз он вырастет после сильного рефакторинга?

Не знаю.

> Во-вторых, каждый отдельный метод содержит их намного меньше :)

за счет того, что методов больше — так каждый может

Точно не каждый. Для этого опыт нужен :)

>А вот calculateAddress вполне может данную ситуацию обрабатывать...

... ничем не хуже вызова функции

еще повтрою, что речь идет именно о функциях однократного использования

На твоем же примере я продемонстрировал наличие проблемы. Код по вычислению адреса вида base+offset*sizeof(T) является системно-зависимым. Посему, лучше скрыть его за каким-то символьным именем. Чтобы когда придет время усложнить его реализацию (и объем) не заниматься рефакторингом, а поправить одно простое определение.

eao197 ★★★★★ ()
Ответ на: комментарий от r
object HelloWorld {
    def f(x: Option[Int]) = x match {
        case None => 123
        case Some(y) => y
        case _ => 456
    }
    def main(args: Array[String]) {
        println( f(Some(7)) )
    }
}

Scala compiler version 2.7.7.final — никаких варнингов

где посмотреть исходник класса Option? его кто-то помешал одерскому запечатать или нет?

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от eao197

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

Все классы нужны на время работы программы. Не аргумент ни в чем.

Что тут такого?


Сайд эффекты. Привет.

Оно где-нибудь изменяется? Оно сказывается еще на чем-то?


Да. Я там выше перечислил неправильные вызовы функций которые можно сделать.

Ты превратил чистый код без возможности нарушить инварианты в код с сайдэффектами и кучей возможностей нарушить инварианты. Хрена се рефакторинг.

И что?


И то. Мой код нещлья вызвать так что сенситивная инфа попадет в чужую систему. Твой можно. От того что ты так не сделал в данной точки зрения - ну так все SQL Injectы и прочие подобные баги тоже происходят не потому что разраб писал специально так код - он написал код где так потенциально можно сделать. У меня код (считай библиотека с одним методом) где потеря сенситивной инфы никогда не попадет нетуда. Твой код (библиотека с кучей методов и классом с кучей методов) где широчайшие возможности наступить на мину.

но в handleUsualAuthSchemeLogin можно будет попасть только из login.


Нет - из любого другого места тоже.

Число шагов просто увеличено, но сами шаги остались теже самые.


1 чистая функция без ошибок инвариантов заменена на кучу нечистых с возможными ошибками инвариантов. Фигасе те же самые.

Никто снаружи метода создать его экземпляры не сможет.


Никто снаружи main не будет вызывать код проекта с 2ГБ исгодников. Нормально - какие тут могут быть баги.

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


Список в студию. Поломай мне инварианты не притрагиваясь к моему коду.

Стоит какому-нибудь разработчику добавить что-нибудь перед вашим первым if-ом и все!


То есть он в локальной точке написал исключительно свой код который произведет действие которое он написал. Это его проблема.

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

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

а, если в Scala нет возможности ограничить контекст использования какого-то вспомогательного класса, то ничего не помешает.


В жабе точно так же.

[code]
public class X {
{
Y.x();
}
private static class Y {
private static void x() {}
}
}
[/code]

Say goodnight.

Если целью исходного кода была, в том числе, и защита от рефлекшена, то тут я ничего не могу возразить.


Целью кода было написать корректную программу. Если вспомнишь иллюстрацией к чему он служил - демонстрация как использование Option помогает в обработке инвариантов. Твой рефакторинг разнес железобетонный код до ненадежного кода с кучей нарушения инвариантов. Твоя цель была что - сделать код хуже? Ну так ты достиг ее по всем параметрам.

r ★★★★★ ()
Ответ на: комментарий от eao197

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

вот и поправим ровно 1 простое определение — причем инлайн

когда инлайн будет слишком жирно — вынесем в функцию, но для этого нужно чтобы там было строчек 10-20

Код по вычислению адреса вида base+offset*sizeof(T) является системно-зависимым.

нет, *именно этот* код не является

обрати внимание, там не было попытки его разыменовать, тем более как тип Т

вполне возможно, там дальше уже шел системно-зависимый код по выковыриванию нужных байтиков, читая 4-ки или 8-ки байт

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

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

где посмотреть исходник класса Option? его кто-то помешал одерскому запечатать или нет?

Он запечатан. Скала язык с nullами и прочим наследованием кейсклассов. Оно в 2.8 deprecated - но все ще возможно.

def f(x: Option[Int]) = x match {
    case Some(y) => y
}

<console>:5: warning: match is not exhaustive!
missing combination           None

       def f(x: Option[Int]) = x match {
                               ^

На счет null и недостижимости _ после exhaustive - напишу enh req.

r ★★★★★ ()
Ответ на: комментарий от r

Сайд эффекты. Привет.

Где?

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

Зашибись аргумент. Адресую его вам же.

eao197 ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

когда инлайн будет слишком жирно — вынесем в функцию, но для этого нужно чтобы там было строчек 10-20

Интересно, почему в вычислениях длины окружности люди пишут 2*PI*R, а не 2*3.1415*R?

нет, *именно этот* код не является

Ну да, если мы запишем: [src]int * p = (int *)(base + offset*sizeof(int)); // (1) int i = *p; // (2)[/src]

То системно зависимым кодом у нас окажется строка (2). Отлично :)

Полагаю, на этом можно закончить.

eao197 ★★★★★ ()
Ответ на: комментарий от eao197

короче, вот:

1. комментарии в виде названий переменных — нормально, хотя и малость говорливо

2. комментарии в виде названий функций — неприемлемо

3. функция должна выделяться тогда, когда цель (или инвариант) функции достаточно далека от средства ее достижения

например, выражение, которое представляет собой средство x=(-b+sqrt(b*b-4*a*c))/2/a до некоторой степени далеко от цели (или инварианта), которая есть а*x*x+b*x+c=0

до какой степени далеко — если читатель не будет помнить эту формулу, значит достаточно далеко, если будет — можно не писать

_____________________________________________

а чтобы сделать п.2 приемлемым, нужны спец. языковые фичи

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от eao197

> Где?

Да весь твой класс handler сплошной сайд эффект.

Зашибись аргумент. Адресую его вам же.


Я новый разраб в проекте - говорю мне надо авторизоваться в другом методе как? Ты говоришь - посмотри в клдассе с методом login есть класс ...Handler который отвечает за автентикацию.


в классе где написан login не притрагиваясь ни к строчке твоего кода пишу:

[code=scala]

def mylogin(login,password) = {
//check
//не знаю зачем я это пишу
new ...Handler(AccountStorage.find(login)).handleUsualAuthSceme()
//ведь и без этого работает
new ...Handler(AccountStorage.find(login)).setup...
)
}
[/code]

тада. Нука расскажи мне почему я так не могу сделать. Потому что у тебя в голове есь какие-то некие соображения по поводу допустимых последовательностей вызовов, а я сделал это недопустимо? Дык я не телепат. Я что при использовании всех твоих библиотек делжен дедукцией выводить логику допустимых инвариантов по исходникам чтобы ими воспользоваться? Это извините меня - шиза и нарушение инкапсуляции.



r ★★★★★ ()
Ответ на: комментарий от eao197

> Интересно, почему в вычислениях длины окружности люди пишут 2*PI*R, а не 2*3.1415*R?

специально и *несколько* раз писал — раньше речь шла о функциях однократного применения, число же пи — многократного (кстати, 3.1416 с этими знаками)

Ну да, если мы запишем: [src]int * p = (int *)(base + offset*sizeof(int)); // (1) int i = *p; // (2)[/src]

То системно зависимым кодом у нас окажется строка (2). Отлично :)

неверно

системно-зависимым окажется каст целого к (int *)

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

> 2*PI*R

хороший пример

канцелярскиv слогом это бы записывалось как lengthOfTheCircleArkOfRadus(R)

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от r

Я новый разраб в проекте - говорю мне надо авторизоваться в другом методе как? Ты говоришь - посмотри в клдассе с методом login есть класс ...Handler который отвечает за автентикацию.

1. Где я такое сказал? 2. Покажите мне нарушение инвариантов не притрагиваясь к моему коду.

eao197 ★★★★★ ()
Ответ на: комментарий от eao197

>1. Где я такое сказал?

Млять.

Я новый разраб в проекте - говорю мне надо авторизоваться в другом методе как?

Жду ответа.

Покажите мне нарушение инвариантов не притрагиваясь к моему коду.


А где я трогал твой код?

r ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

> канцелярскиv слогом это бы записывалось как lengthOfTheCircleArkOfRadus(R)

Не, circleLength.

И обязательно нужно вызывать circleLength(R), чтобы можно было подставить тело, которое бы возвращало заранее вычесленные значения для фиксированных R :)))

eao197 ★★★★★ ()
Ответ на: комментарий от r

> На счет null и недостижимости _ после exhaustive - напишу enh req.

напиши

но уровень языка и внимание к надежности это характеризует

матчинг на кейс классах это чуть ли не первая (хронологически) фича в скале, и до сих пор все вот так

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

>матчинг на кейс классах это чуть ли не первая (хронологически) фича в скале, и до сих пор все вот так

Ну не так и плохо. Пока только не детект unreachable на _. Если туда написать любой другой кейс - он увидит что код мертвый.

r ★★★★★ ()
Ответ на: комментарий от r

Я новый разраб в проекте - говорю мне надо авторизоваться в другом методе как?

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

А где я трогал твой код?

А где у меня в коде вот это все:

new KnownUserLoginHandler(requ, "x", "y", user{ authSceme="PETRIVKA"}).handleUsualAuthSchemeLogin()

new KnownUserLoginHandler(requ, "x", "y", user).handleUsualAuthSchemeLogin().setupSuccessfulAuthResult

val h = new KnownUserLoginHandler()
h.handleInactiveUserLogin 
h.setupSuccessfulAuthResult

У меня ничего подобного нет. Это все ваша восполенная фантазия. Есть конкретная реализация метода login. Проблемы с инвариантами в ней есть?

eao197 ★★★★★ ()
Ответ на: комментарий от eao197

> Не, circleLength.

я разочарован

такое короткое и простое название

предыдущие навроде setupSuccessfulAuthResult были намного длиннее и завораживающе таинственны...

в коротком стиле оно бы было uncheckedLogin, или uncheckedEnter, или даже doLogin, или вовсе enter

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от r

Да весь твой класс handler сплошной сайд эффект.

Кстати, у вас, видимо, толкование термина «сайд-эффект» сильно отличается от моего. Не могли бы вы либо раскрыть свою трактовку термина, либо же показать пальцем на проявления сайд-эффектов в моем классе?

Общие слова не прокатят.

eao197 ★★★★★ ()
Ответ на: комментарий от eao197

>У вас есть ваш login и у вас есть новый разработчик, которому нужно выполнить аутентификацию.

Посмотри в класс с методом логин. Твой ответ?

У меня ничего подобного нет. Это все ваша восполенная фантазия


Это все пишу я. Я использую классы которые написал ты. Компилится. НЕ работает. Я пишу в IDE new ...Handler(...). нажимаю комплишен - вижу тучу методов. Вызываю. Например передал в параметры конструктора корректный логин пароль, вызываю setup - клево залогинились. Передаю некорректный - вызываю setup. Снова залогинились. Я в недоумении - почему?

Я прихлжу к тебе и говорю - я вон тут вызвал метод твоего класа а ему вообще наплевать на то что туда хоть нулы передал - он все равно логинит. Что делать?

Жду ответа. Расскажи мне как опытный разработчик что мне делать - я ж пользую твой мегакласс.

Проблемы с инвариантами в ней есть?


Ты что читать не умеешь? Я тебе их уже три страницы перечисляю.

r ★★★★★ ()
Ответ на: комментарий от eao197

>Не могли бы вы либо раскрыть свою трактовку термина, либо же показать пальцем на проявления сайд-эффектов в моем классе?

У тебя куча функций handle* без параметров вообще. А результат работы почему-то разный от случая к случаю.

r ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

предыдущие навроде setupSuccessfulAuthResult были намного длиннее и завораживающе таинственны...

Пять баллов! :))) Мне понравилось, спасибо.

в коротком стиле оно бы было uncheckedLogin, или uncheckedEnter, или даже doLogin, или вовсе enter

doLogin уже было ;)

Если серьезно, то вычитал когда-то, что если метод что-то меняет (т.е. его можно классифицировать как command или action), то его название должно начинаться с глагола. Т.е. doLogin, forceLogin, handleLogin.

Если же метод является чистой функцией (т.е. его можно классифицировать как query или predicate) то начинать название с глагола не рекомендуется. Т.е. uncheckedLogin можно воспринимать как предикат, который возвращает true или false.

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

eao197 ★★★★★ ()
Ответ на: комментарий от eao197

>Если серьезно, то вычитал когда-то, что если метод что-то меняет (т.е. его можно классифицировать как command или action), то его название должно начинаться с глагола. Т.е. doLogin, forceLogin, handleLogin.

Холи шит! login - это глагол!

r ★★★★★ ()
Ответ на: комментарий от r

У тебя куча функций handle* без параметров вообще. А результат работы почему-то разный от случая к случаю.

Результаты работы точно такие же, как в случае вашей функции login. Что на вход пришло, то в respond или в состояние сессии и попало. Ни больше, ни меньше. Поэтому сайд эффектов ровно столько же.

Посмотри в класс с методом логин.

Это пять!

Твой ответ?

Выдели из кода login повторно-используемый код, оформи его в виде отдельного класса, покрой тестами и принеси на code review. А дальше видно будет.

Это все пишу я. Я использую классы которые написал ты.

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

eao197 ★★★★★ ()
Ответ на: комментарий от r

Холи шит! login - это глагол!

См. http://lingvo.abbyyonline.com/ru/en-ru/login: login

1) начало сеанса (работы с терминалом)

2) вход в систему

3) регистрационное имя (сообщаемое пользователем при входе в систему)

В 1) и 3) случаях login, насколько мне подсказывают остатки образования, вовсе не глагол.

eao197 ★★★★★ ()
Ответ на: комментарий от eao197

> Поэтому сайд эффектов ровно столько же.

Ахренеть. Ну если ты уже начал придумівать что такое сайд эффекты.

Выдели из кода login повторно-используемый код, оформи его в виде отдельного класса, покрой тестами и принеси на code review. А дальше видно будет.


Ну вот я и пишу тесты. Передал правильные - залогинился. Передал неправильные снова залогинился - что мне делать? Я использую твой код. Повторно. ТАм наверное бага. Ты глянь - а то я зову твои методы а они логинят меня чтобы я не передал.

Ну так это уже ваши проблемы, сударь


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

Разрешения на повторное использование этого кода вам никто не давал.


Охрененно вы пишете наверное проекты. Там у вас везде размечено где чей код и где у кого высокого ползволения испрашивать на вызов тех или иных методов? А можно там какой нить USB интерфейс воткнуть в тебя чтобы плугин к IDE написать и оно мне не показывало в комплишене методов на которые ты лично не давал разрешения?

r ★★★★★ ()
Ответ на: комментарий от r

> Поэтому сайд эффектов ровно столько же.

Ахренеть. Ну если ты уже начал придумівать что такое сайд эффекты.

Ничего я не придумываю. Все сайд-эффекты определены еще в вашем коде — это обращение к respond и конструкция 'request.session(«user») = user'. Это как раз то, что изменяет состояние мира после возврата из login. Мой код приводит к точно таким же изменениям.

Ну вот я и пишу тесты. Передал правильные - залогинился. Передал неправильные снова залогинился - что мне делать? Я использую твой код. Повторно. ТАм наверное бага. Ты глянь - а то я зову твои методы а они логинят меня чтобы я не передал.

Внимательно читаем постановку задачи: Выдели из кода login повторно-используемый код, оформи его в виде отдельного класса

Раз тесты не проходят, значит не правильно выделил и не правильно оформил. Значит руки не оттуда растут. Будем вправлять.

Там у вас везде размечено где чей код и где у кого высокого ползволения испрашивать на вызов тех или иных методов?

У нас нормальная разработка и у библиотек есть публичный интерфейс и детали реализации. Если кому-то взбрело в голову на свой страх и риск залезть в детали наплевав разграничение на интерфейс/реализацию, то с такими случаями мы разберемся отдельно.

eao197 ★★★★★ ()
Ответ на: комментарий от r

> Ну не так и плохо. Пока только не детект unreachable на _. Если туда написать любой другой кейс - он увидит что код мертвый.

Может, case _ матчит null?

pitekantrop ★★★ ()
Ответ на: комментарий от pitekantrop

>Может, case _ матчит null?

Матчит. Но если написать проверку еще и на нулл а потом _ - все равно пропускает.

r ★★★★★ ()
Ответ на: комментарий от eao197

>Мой код приводит к точно таким же изменениям.

Твой код с сайдэффектами - это класс ..Handler. У меня такого не было.

Выдели из кода login повторно-используемый код, оформи его в виде отдельного класса


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

Раз тесты не проходят, значит не правильно выделил и не правильно оформил.


Я вообще ниче не выделял - я твой класс пользую as is. Потому как вроде как то что надо - передал параметры автентикации - оне должен залогинить. Да вот беда он меня логинит все время чтобы я не передал.

Наверное там таки бага. Я вызываю 4 разных метода handle* и он делает что попало. Передал схему автентикации петровка - вызвал handleUsusal - попал на сенситивную инфу. Куда не кинь всюду клин. 5 методов, звать можно как угодно, в какой угодно последовательности - а результаты такое мочат что я в полной растерянности - где же этот единственный тот самый правильный порядок? Ну дядя - подскажи - два часа вожусь с твоей либой.

Значит руки не оттуда растут.


Я даже знаю у кого.

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


А публичность интерфейса как определяется? Я вон полез писать отдельный сервис в класс с логином - что-то мне комплишен расказывает что можно звать что угодно. Знгачит публично. Или есть какие-от другие критерии публичности?

Если кому-то взбрело в голову на свой страх и риск залезть в детали наплевав разграничение на интерфейс/реализацию


Не вижу у тебя никаких интерфейс-реализация - вижу класс с методами 5 методами которые мне доступны в этом скоупе - а мочат они такое что волосы заворачиваются.

r ★★★★★ ()
Ответ на: комментарий от r

>У нас нормальная разработка и у библиотек есть публичный интерфейс и детали реализации.

К стати а в деталях реализации у вас можно писать любое неинвариантное неинкапсулированное говно - я так понимаю?

Тогда мы вернемся к инкапсуляции функции main и 2ГБ проекту.

r ★★★★★ ()
Ответ на: комментарий от r

> Матчит. Но если написать проверку еще и на нулл а потом _ - все равно пропускает.

ы, ыы, ыыы!!!!!

так значит матч не exaustive, а компилятор молчит об этом как партизан на допросе?

ну и чем это лучше си, где можно спокойно разыменовать нулевой указатель?

и тогда становится неудивительно, что компилятор скалы до сих пор падает

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

>так значит матч не exaustive, а компилятор молчит об этом как партизан на допросе?

матч exhaustive. это unreachable code.

r ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

> ы, ыы, ыыы!!!!!

так значит матч не exaustive, а компилятор молчит об этом как партизан на допросе?

ну и чем это лучше си, где можно спокойно разыменовать нулевой указатель?

и тогда становится неудивительно, что компилятор скалы до сих пор падает

Ну и чем это хуже жабы с её null-ами и NullPoinerException?

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

pitekantrop ★★★ ()
Ответ на: комментарий от r

> матч exhaustive. это unreachable code.

Думаю, что он имел в виду, что компилятор не ругается, когда отсутствует case null.

pitekantrop ★★★ ()
Ответ на: комментарий от r

матч exhaustive. это unreachable code.

прям я так и поверил

$ cat test1.scala 
object HelloWorld {
    def f(x: Option[Int]) = x match {
        case None => 123
        case Some(y) => y
    }
    def main(args: Array[String]) {
        println("---")
        println( f(null) )
        println("---")
    }
}
$ scalac test1.scala 
$ scala HelloWorld
---
scala.MatchError: null
        at HelloWorld$.f(test1.scala:2)
        at HelloWorld$.main(test1.scala:8)
        at HelloWorld.main(test1.scala)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at scala.tools.nsc.ObjectRunner$$anonfun$run$1.apply(ObjectRunner.scala:75)
        at scala.tools.nsc.ObjectRunner$.withContextClassLoader(ObjectRunner.scala:49)
        at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:74)
        at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:154)
        at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от pitekantrop

> Ну и чем это хуже жабы с её null-ами и NullPoinerException?

тем, что сильно сложнее жабы

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

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

только после того, как ты предложишь, как из говна сделать конфетку

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

>прям я так и поверил

Да я про свой код. Сейчас матчинг ищет не-exhaustive код (пока ему не отламывают крылья гуардами) и мертвый где может - хотя багов там сча много. Exhaustiveness проверить в общем случае нельзя - потому что класс может быть не sealed + тянущуюся проблему наследования от кейсклассов

case class A

case class B extends A //такое в 2.8 задепрекейтили но еще не запретили, а до этого все пытались запилить модель где так можно.

B match {
case A => ...ы?
}

там не все так просто - и это понемногу лечат.

r ★★★★★ ()
Ответ на: комментарий от r

> B match { case A => ...ы? }

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

match { case В => ... case A => ... }

если ставить В раньше А; а где проблема-то?

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от r

т.е. «матчим сначала самый специфичный»; если он вдруг оказывается не перед менее специфичным, получаем недостижимый код и ошибку компиляции; как будто все хорошо

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

>> Ну и чем это хуже жабы с её null-ами и NullPoinerException?

тем, что сильно сложнее жабы

Давай, покажи мне, как сделать простой pattern matching на жабе. Что толку от её простоты, если большинство удобных абстракций выражаются на жабе так, что можно повеситься?

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

только после того, как ты предложишь, как из говна сделать конфетку

Вспомнился основной закон органической химии: если смешать килограм мёда и килограм говна, то получится 2 килограма говна. :)

pitekantrop ★★★ ()
Ответ на: комментарий от www_linux_org_ru

>а где проблема-то?

case class A(x:Int)
case class B(x:Int) extends A(x*2)

B(5).x == A(5).x ?

B(5) match {
case A(x) => чему равен x?
}

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

r ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.