LINUX.ORG.RU

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

 , , ,


1

4

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

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

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

★★★★★

Проверено: maxcom ()
Последнее исправление: Zhbert (всего исправлений: 3)
Ответ на: комментарий от eao197

Упс, нужно было так:

private def doLogin(login: String, password: String): LoginResult = {
  if( null == login ) Failure("You should provide login")
  else if( null == password ) Failure("You should provide password")
  else AccountsStorage.find(login) match {
    case None => Failure("User not found")
    case Some(user) => handleUserLogin(user, login, password)
  }
}

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

У вас каша в голове, не стоит злоупобрелять разными yet-another-monad-tutorial. Прочитайте про lambda calculus & основы теории категорий

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

Могу ошибиться в названии. В теории категорий совершенно не силен. Но смысл остается тем же. Return соответствует «natural transformation eta». Или просто анонимно придраться захотелось? Мой же комментарий по поводу многочисленного использования return не является придиркой. Такое использование действительно является моветоном, плохим стилем.

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

> Могу ошибиться в названии.

На пальцах: в хаскелле «return» возвращает функцию, которая возвращает переданное значение «return», но не просто значение, а значение, вложенное внутрь типа «монада».

Так как значение вложенное, то его просто так не извлечь. Но можно использовать с помощью «bind»

Надеюсь, что хоть немножко стало понятнее, что return в классических императивных языках не имеет ничего общего (кроме названия) с тем, про что вы упомянули

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

Неправда ваша. Все способы для написания более понятных программ - хороши. Так и «множественные точки выхода» aka «return». В ряде случаев это уменьшает число вложенных условий, что как нельзя лучше сказывается на читаемости + восприятия (путём упрощения контекста).

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

anonymous
()
Ответ на: комментарий от dave

> Но это неинтересно.

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

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

Может быть, возникло недопонимание? Я и написал, что return в F# - это совсем не то, что в Scala. А что касается монад, то в моей копилке есть несколько штук самоизобретенных. Что касается теории категорий, давно хотел изучить ее, но как-то мотивации все не хватало :)

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

> Может быть, возникло недопонимание?

Скорее всего

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

misuse of unit testing detected. Юнітом тут является функція process().

Misunderstanding detected. Речь шла о ситуациях, когда process будет слишком большим unit-том для тестирования. Ведь, как я понял, process — это login из исходного примера.

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

login - атомарная операция и является отличным кандидатом на то чтобы быть юнитом. Разбивать его на подюниты чтобы проверить каждый if отдельно - значит лишать себя удовольствия проверить интеграцию между этими подоперациями. То есть successful execution of unit tests почти ничего не даст.

Всё, конечно же, зависит от ситуации. Но обычно method-based тестирование даёт плачевные результаты по покрытию контракта.

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

>Может вы сможете показать, где там «испуг»?

Легко.

2. Контроль со стороны компилятора за полнотой покрытия.

Использовались ли какие-то из этих преимуществ в вашем случае с Option[User]? Нет.



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

Я это даже комментировать не стал настолько этот посыл феерическая чушь.

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

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

Более-менее полную верификацию, кажется, делают инструменты типа Ada SPARK, Perfect Developer, Frama-C. Только вот ограничения там еще суровее, а никаких зависимых типов и близко нет. :)

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

AlexRK
()
Ответ на: Куда нам до ваших высот от anonymous

Ахаха. :) Поймали, поймали.

Ну, чего не скажешь в горячке спора. Главное-то ведь что?

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

(c)

:)

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

> Не могли бы вы разъяснить, как следует воспринимать Фаулера — как эксперта, чьи рекомендации следует использовать для критики кода, или же «его надо пережить»?

Очень просто. Видел когда нибудь как учат совсем маленьких детей? Например счету на спичках. Обозначает ли это что счет на спичках - экспиертная методика обучению арифметике, и все надо считать на спичках? Нет не обозначает. Обозначает что неэффективно учить детей считать на спичках? Нет - тоже не обозначает. Что из этого следует? Из этого следует что любая методология имеет область применения.

Теперь вернемся к software engineering. Есть такая контора называется Carnegy Melon University. Они разработали методологию оценки зрелости процессов управления - называется SEI/CMM - software engineering institute/capability maturity model. В этой модели есть пять уровней.
1. Chaotic
2. Repeatable
3. Defined
4. Managed
5. Optimizing

Все эти профессиональные консультаны/литераторы вроде фаулера или бека оказываются весьма полезны когда надо осуществить переход от уровня 1 к уровню 2. Уровень два - это существование хоть каких нибудь понятных процессов, _возможно_ (крайне важное слово) с консистентными результатами. То есть грубо говоря юнит тест может быть полезен а может быть бесполезен - но уровень два - это хотя бы он будет написан. Все эти популярные методологии вроде extreme programming или смешной scrum - оказываются весьма полезны если цель выйти из хаоса хоть куда нибудь. Design Patterns/Refactorng Practices - относится тоже к этому - чтобы из совсем хаотичного неструктурированного кода получить хоть насколько нибудь консистентный.

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

Так вот Фаулер - это как раз этот директор. От того что он заорет что это ветвление надо зарефакторить в абстрактную фабрику - не проистекает его безусловная правота. Зависит от того на кого он орет. Если он орет в команде которая работает на CMM-1 - его можно слушать. Но если он заорет в команде которая раотает на уровне 3 и выше - то Фаулеру понадобить чуть больше причин для обоснования своего крика чем те которые указаны в книжке рефакторинг, потому что у команды CMM-3 могут найтись причины не хуже фаулеровских, а то и получше почему они делают не так.

Теперь дальше - почему я тебя послал изучать Фаулера. В твоем посте в блоге ты написал:

Чтобы получилось так, как привык писать я сам. ....Т.е. не факт, что получится что-то принципиально иное. Но, будет оформлено более привычно для меня :)


То есть ты руководствуешься какимто астральными критериями вида «нравится - не нравится».

Когда я попытался привести некие формальные метрики выражаемые в цифрах (то есть предложил ввести формальне метрики и согласно им оценивать код) ты написал что это:

А могут (и обязательно будут) и неадекватные реакции.


То есть для тебя нравится-не-нравиться - это самое оно, а предложение оценить согласно формальным метрикам - это неадекватная реакция.

Для меня программирование - инженерный процесс. Не знаю что он для тебя. Потому у меня люди которых я отбираю на собеседовании обладают полной свободой, и собеседование у меня с целью выяснить справятся ли они с этой свободой с адекватными результатами. У нас всех разные подходы разные технологии и разные принципы. Я не заставляю их переписывать ifы на pattern matching в их проектах - оценка их происходит не по количеству ifов а по результатам сделанных проектов. Они могут принимать какие угодно решения - потому что рефакторинг или паттерны это не фетишь, и самоценности они не имеют - это практики которые могут улучшать или не улучшать результат - проект.

Ты же, по твоему собственному признанию:

Который я в данной заметке попробую отрефакторить. Чтобы получилось так, как привык писать я сам. И как я требую поступать от своих подчиненных.


Я перереставлю фразы чтобы подчеркнуть на что я обращаю внимание:

я требую поступать от своих подчиненных...(так)...Чтобы получилось так, как привык писать я сам.


Вот поэтому я и посылаю тебя общаться с Фаулером - он для тебя как раз.

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

Теперь дальше - по самим личностям.

Все они кроме Гаммы - профессиональные консультанты. Крейг Ларман - консультант (к стати его книгу я считаю лучше чем GoF, хотя их обе надо прочитать). Виллисидес был преподавателем. Хелм - консультант. Джонсон - преподаватель. Фаулер консультант. Бек - консультант. Единственный практик - Гамма, он занимается Eclipse Project.

То есть кроме Гаммы они все продают книги, курсы и треннинги. Обращаясь к истории, например возникновения XP - Бек был консультантом в проекте C3. Несмотря на полезную методологию которая из этого выработалась - не стоит забывать о трех вещах:

1. область применения ее - хаос - CMM-1. Сами по себе записи юзерсторис на карточках и процесс сортировки - не серебрянная пуля (о чем к стати они сами пишут через строчку). Просто на уровне CMM-1 хорошо если будет хотя бы это - и то хорошо. Я XP и RUP уже занимался тогда когда весь этот миллион книжек изданных Питером был еще даже не написан, в свое время жарко флеймили на xprogramming.ru. Я отлично знаю область его применения, знаю его недостатки, и насмотрелся на кучу оголтелых евангелистов у которых есть такая стандартная мантра когда указываешь на недостатки «я знаю что XP работает». Сейчас понеслась вторая волна SCRUM - опять эти оголтелые коучи, больше похожие на продавцов библий, носятся по софтверным конторам повторяя всю ту же мантру «я зная что скрум работает» и пытаются продать JUnit и стояние по утрам в кругу как «именно то что надо вашей компании». Мне лично их даже жалко - через пару лет они поймут какой херней страдают. Но это лирика.

2. По собственному признанию Бека он никогда не писал серьезного «науко»-емкого софта - вроде компиляторов - и потому не знает подойдет ли вся та фигня что он пишет в книгах для него. То есть все что он писал в жизни - это большую бухгалтерию для крайслера на смоллтолке. А самое большое его программистское достижение - JUnit.

Я думаю никто не будет спорить, что если какому нить Одерскому или Теренсу Парру предложить «отрефакторить» их поректы по Файлеру и задизайнить по GoF - то можно услышать набор отборного мата, который будет обозначать, что вы зашли не в ту церковь.

3. Взаключение по Беку - проект C3 то несмотря на вкатанные туда миллионы, XP, паттерны, рефакторинг и кучу других ритуалов поклонению процессу, не умилостивил богов достаточно, чтобы быть успешным - это был Epic Fail.

И все эти консультанты сами не стоят за крутыми работающими софтверными проектами.

Чуть более конкретнее например у Фаулера в Рефекторинг:
http://refactoring.com/catalog/removeSettingMethod.html

This the example at the bottom of page 301 (that uses initialize(id)) just does not compile. (My apologies... This also means that the mechanics is incorrect.


Брюс Эккель - еще один продавец бумаги образцово облажался в своем посте Static Typeng vs Strong Testing https://docs.google.com/View?id=dcsvntt2_25wpjvbbhk

Где он противопоставляет статическую типизацию примеру на питоне, где не надо разного бойлерплейта вроде обявление интерфейса), даже не подозревая, что такое возможно и в статических языках - ocaml выведет это сам, в скале можно указать структурный тип, и этот пример почти добуквенно будет работать и в статическом языке. Но означает ли это что его книжки Thinking in Java/C++/Python - гавно?

Нет - он пишет хорошие книжки. Как и файлер и Бек, и Банда четырех.

Но только не надо думать что они бохи которые кругом правы.

r ★★★★★
()
Ответ на: Куда нам до ваших высот от anonymous

>предложения Фаулера для упрощения восприятия кода неверны

Ну - это вообще блеск. Фаулер же видать известный специалист в области психологии восприятия.

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

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

Я это даже комментировать не стал настолько этот посыл феерическая чушь.

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

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

> Очевидно, что у нас с тобой совершенно разные взгляды на этот вопрос, поэтому здесь я с тобой просто не согласен.

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

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

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

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

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

Редкий по степени бредовости поток сознания.

Когда я попытался привести некие формальные метрики выражаемые в цифрах (то есть предложил ввести формальне метрики и согласно им оценивать код) ты написал что это:

Неадекватность появилась не в факте применения метрик, а:

- во-первых, в самом наборе предложенных метрик, поскольку там был всего лишь один объективный критерий — наличие сайд-эффектов, но

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

Например, была метрика — «помещаемость кода на экране». По этому критерию результаты обсфукции будут намного превосходить нормальный код. Т.е., если вы примените такую метрику, например, к победителям конкурса International Obsfucated C Code Contest, то для них эта метрика будет давать наивысшие балы.

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

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

То есть для тебя нравится-не-нравиться - это самое оно

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

Я перереставлю фразы чтобы подчеркнуть на что я обращаю внимание

А вот не нужно вольно обращаться с чужими словами и выдавать свои домыслы за чужие высказывания.

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

>>надо было кидать туда предикат, и все

Нет. Там precision strike. Константная скорость доступа независимо от количества записей.

кстааааааати

а как скала решает эту проблему?

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

поэтому, например, в шарпе find(_.key == user.authScheme) может получить доступ непосредственно к user.authScheme, а не только к предикату

как это сделать в скале?

З.Ы. а у тебя дешево и сердито решить проблему можно так: назвать не find, а find_login

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

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

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

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

>Но это ваша чушь, поскольку ничего подобного я не говорил.

Таневже. Ну так раскрой более полно почему ни первое не второе там не работает.

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

>Редкий по степени бредовости поток сознания.

Я не сомневался что тебе понравится.

- во-первых, в самом наборе предложенных метрик, поскольку там был всего лишь один объективный критерий


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

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

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


Очевидно кому? Покажите мне этих людей которые считают что утверждение «35 строк кода меньше чем 93 строки» - неправильным.

По этому критерию результаты обсфукции будут намного превосходить нормальный код


И?

Т.е., если вы примените такую метрику, например, к победителям конкурса International Obsfucated C Code Contest, то для них эта метрика будет давать наивысшие балы.


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

Между тем, в вашем списке метрик не было ни одной метрики


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

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


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

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


Правда?! Поэтому ты решил меряться субьективно, а попытку перевести все в объективные оценки назвал неадекватом.

А вот не нужно вольно обращаться с чужими словами и выдавать свои домыслы за чужие высказывания.


Там никаких домыслов не было. Это ты написал.

И эти люди еще философтствуют об «адекватности» аргументации.

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

>в шарпе она решена — функция, которая получает не слишком сложно сконструированную анонимную функцию, может разобрать ее как синтаксическое дерево

Expression Trees она не умеет. Дискуссии идут.

З.Ы. а у тебя дешево и сердито решить проблему можно так: назвать не find, а find_login


Класс стораджа универсальный, хранит не только юзеров.

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

>а как скала решает эту проблему?

Но есть плугионвая архитектура компилятора. На уровне плугинов это решить можно.

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

Ну так раскрой более полно почему ни первое не второе там не работает.

Тема давным-давно раскрыта. Просто перечитайте, наконец, то, что вам пишут, внимательно.

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

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

Я ничего не предлагал. Так что все претензии ко мне по этому поводу идут в сад.

На мой взгляд, ваш код не демострирует повышения надежности программ за счет Option[T] (как это было вами заявлено). К тому же код перенасыщен мелкими подробностями, что затрудняет его восприятие.

Лично мне не нужны метрики, чтобы обосновать собственное ощущение «затрудняет».

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

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

Есть претензии - давай уточняющую метрику которая ограничивает скоуп применеия основной.

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

Что ж ты их не привел со ссылками?

Метрики понадобились вам, а не мне.

Поэтому ты решил меряться субьективно, а попытку перевести все в объективные оценки назвал неадекватом.

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

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

>Тема давным-давно раскрыта. Просто перечитайте, наконец, то, что вам пишут, внимательно.

Очень-очень адекватно. Тебя попросили конкретно показать где, потому как предмет спора сам факт, что ты что-то там показал, на что ты ответил - «иди читай еще раз». Очень адекватненько так.

Ты так с людьми на собеседовании общаешься? Когда тебя просят повторить задание ты случайно не посылаешь их с «я уже давным давно все рассказал»? Адекватность так и прет.



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

>Я ничего не предлагал.

Правда чтоле?

На мой взгляд, ваш код не демострирует повышения надежности программ за счет Option[T]


На мой взгляд брюнетки сексуальнее блондинок. Мы здесь про инженерную дисциплину разговариваем или вкусы обсуждаем?

Лично мне не нужны метрики, чтобы обосновать собственное ощущение «затрудняет».


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

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


На мой взгляд ты слишком злоупотребляешь выражением «на мой взгляд», что явно делаешь для того, чтобы когда позже тебя этот взгляд обосновать можно было слить, что это такое «субьективное ощущение». Так что на мой взгляд пока ты не начнешь использовать такой немаловажный компонент спора как приведение аргументов - обсуждать твои «взгляды» дальше бессмысленно.


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

Очень-очень адекватно. Тебя попросили конкретно показать где, потому как предмет спора сам факт, что ты что-то там показал, на что ты ответил - «иди читай еще раз». Очень адекватненько так.

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

А итог написанного там прост: в приведенном вами коде паттерн-матчинг никаких преимуществ над if-ами не демострирует. Следовательно, смысла применять его не было. Более того, он делает простую логику бинарного выбора доступых вариантов сложнее, чем это требуется. А полнота этой логики в данном случае не может быть проверена компилятором.

Больше я повторять не буду.

Ты так с людьми на собеседовании общаешься?

Пора вам указать на то количество откровенной херни, которую вы тут выплескиваете совершенно не по теме. То мой стиль работы хотите пообсуждать, то байки про CMM рассказываете, то Фаулера с Беком опускаете, теперь вот на собеседования вас потянуло.

Воздержитесь от потоков сознания, пожалуйста.

eao197 ★★★★★
()

я тут обрамил код r так, что он стал компилироваться, и логинит васю пупкина (частично заюзав код из блога, указанного еао197)

сам код чуть поправлен: s/log.debug/debug/

дальше будет рефакторинг

object LoginDemo
{
    // @rest.Method(httpMethod = Array(POST))
    def login(request: rest.Request,
            login: String,
            password: String) =
    {
        debug("accessing login... " + login)

        if( login == null || password == null ) respond(UNAUTHORIZED, "You should provide login and password")
        else AccountsStorage.find(login) match {
            case None => respond(UNAUTHORIZED, "User not found")
            case Some(user) if user.inactive => respond(UNAUTHORIZED, "Account is inactive")
            case Some(user) if user.authScheme == "PETRIVKA" =>
                if( user.passwordMatches(password) ) request.session("user") = user
                else respond(UNAUTHORIZED, "Authentication failed")
            case Some(user) => AccessStorage.access.auth_configs.find(_.key == user.authScheme) match {
                case None => respond(FORBIDDEN, "Unknown authentication scheme: " + user.authScheme)
                case Some(scheme) =>
                    debug("authenticating with " + scheme.command)
                    val exec = Runtime.getRuntime.exec(scheme.command.replace("{login}", login).replace("{password}", password))
                    if( exec.waitFor == 0 ) request.session("user") = user
                    else respond(UNAUTHORIZED, "Authentication within " + scheme.key + " failed")
            }
            case _ => respond(UNAUTHORIZED, "Authentication failed")
        }
    }
    def respond(code: Int, message:String) = println("respose: "+code+" "+message)
    def debug(message:String) = println("debug: "+message)

    val UNAUTHORIZED = 401
    val FORBIDDEN = 403

    def main(args: Array[String] ) {
        val request = new rest.Request
        login( request, args(0), args(1) )
        debug( "request.session(\"user\")="+request.session("user") )
    }
}
class User {
    val login = "vasya"
    val inactive = false
    val authScheme = "PETRIVKA"

    def passwordMatches(password: String) = (password=="pupkin")
}
class AuthScheme {
    val key = "simple"
    val command = "/bin/true"
}
object AccountsStorage {
    def find(login: String): Option[User] = list.find( _.login==login )
    val list = List[User]( new User() )
}
object AccessStorage {
    object access {
        val auth_configs = List[AuthScheme]( new AuthScheme )
    }
}
package rest {
    class Request {
        val session = scala.collection.mutable.Map[String, Any]()
    }
}
www_linux_org_ru ★★★★★
()
Ответ на: комментарий от r

Мы здесь про инженерную дисциплину разговариваем или вкусы обсуждаем?

Это уж вы определитесь. Поскольку, как только вы вставили в match с Option пару гуардов, ни о какой надежности Option

Потому что ты сам лично не утрудил себя даже какими-либо обоснованиями.

Еще раз. Ваш код мне не понравился (почему см.выше в обсуждении). Свой вариант кода я привел.

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

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

> Класс стораджа универсальный, хранит не только юзеров.

в воздухе явно запахло РНР...

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

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

Гражданин r. Есть объективная метрика, хорошо отражающая сложность кода - цикломатическая сложность.

Посчитайте ее для вашего кода. Если она больше 10 - ваш код, скорее всего, плохой.

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

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

> Еще раз. Ваш код мне не понравился (почему см.выше в обсуждении). Свой вариант кода я привел.

твой код сильно хуже по метрике «строки кода при соблюдении минимального общепринятого стандарта кодирования (который легко отрежет obfucated code)»

2-й код из блога, который ты привел, не эквивалентен — там убран FORBIDDEN

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

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

> Насколько я могу судить на первый взгляд, у вас она раза в 2 превышает норму. :)

давай тулзу для подсчета или посчитай руками

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

твой код сильно хуже по метрике «строки кода при соблюдении минимального общепринятого стандарта кодирования (который легко отрежет obfucated code)»

О такой метрике я так же не слышал.

Поверхностная информация о метриках: http://www.ibm.com/developerworks/ru/edu/0108novich/section2.html

В особенности рекомендую пункт «Итого по SLOC» :)

2-й код из блога, который ты привел, не эквивалентен — там убран FORBIDDEN

Да, наверное, ты прав. Но я не автор того кода и даже лично с ним не знаком :)

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

А у меня нет такой цели — критиковать. Мне не понравился исходный код и я посчитал, что он не демонстрирует заявленных целей. О чем и сказал. Но, поскольку я придерживаюсь принципа «критикуешь — предлагай», то я счел необходимым написать свой вариант. Написал. Т.е. свою задачу я счел выполненой.

Но дальше началось некорректное и абсурдное, местами, сравнение. Вот эту абсурдность и хотелось устранить. Ну или хотя бы сделать очевидной.

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

Упс, нужно было так:

private def doLogin(login: String, password: String): LoginResult = {
  if( null == login ) Failure("You should provide login")
  else if( null == password ) Failure("You should provide password")
  else AccountsStorage.find(login) match {
    case None => Failure("User not found")
    case Some(user) => handleUserLogin(user, login, password)
  }
}

Я имел в виду переписать только for, чтобы можно было сравнить. А здесь уже handleUserLogin появился. Сможешь переписать не вводя новых функций? Я даже предложил бы чуть поменять код, чтоб нагляднее было:

  def authenticate(login: Option[String], password: Option[String]) =
    for {
      login <- login.toRight("You should provide login").right
      password <- password.toRight("You should provide password").right
      user <- AccountsStorage.find(login).toRight("User not found").right
      activeUser <- Either.cond(!user.inactive, user, "Account is inactive").right
      scheme <- findAuthScheme(activeUser.authScheme).toRight("Unknown authentication scheme: " + activeUser.authScheme).right
      authenticatedUser <- Either.cond(scheme.check(login, password), activeUser, "Authentication within " + scheme + " failed").right
    } yield authenticatedUser

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

Я имел в виду переписать только for, чтобы можно было сравнить.

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

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

отличный аргумент и обоснование

> > предложения Фаулера для упрощения восприятия кода неверны

Ну - это вообще блеск. Фаулер же видать известный специалист в области психологии восприятия.

Итак, это все ваши аргументы (я бы вообще это к аргументан на отнёс)? Видать, вы более известный специалист, чем Фаулер?

Следуя вашей же логике и метрике - вы вообще никто, так о чём разговор?

Может таки потрудитесь снизойти до ответов на заданные вам конкретные вопросы и перестанете нести несусветную чушь, отвечая на выдуманные вами же вопросы?

anonymous
()
Ответ на: комментарий от AlexRK

Посчитал руками: приближенное значение 16.

похоже, ты в 2 раза ошибся

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

если считать ветками две ветки в login == null || password == null, тогда будет 9 ( || равнозначно иф-у, однако в данном коде его можно заменить на просто | )

.        if( login == null || password == null ) respond(UNAUTHORIZED, "You should provide login and password")
         else AccountsStorage.find(login) match {
             case None => respond(UNAUTHORIZED, "User not found")
.            case Some(user) if user.inactive => respond(UNAUTHORIZED, "Account is inactive")
.            case Some(user) if user.authScheme == "PETRIVKA" =>
.                if( user.passwordMatches(password) ) request.session("user") = user
                 else respond(UNAUTHORIZED, "Authentication failed")
.            case Some(user) => AccessStorage.access.auth_configs.find(_.key == user.authScheme) match {
                 case None => respond(FORBIDDEN, "Unknown authentication scheme: " + user.authScheme)
.                case Some(scheme) =>
                    debug("authenticating with " + scheme.command)
                    val exec = Runtime.getRuntime.exec(scheme.command.replace("{login}", login).replace("{password}", password))
.                    if( exec.waitFor == 0 ) request.session("user") = user
                     else respond(UNAUTHORIZED, "Authentication within " + scheme.key + " failed")
            }
www_linux_org_ru ★★★★★
()
Ответ на: комментарий от eao197

> А у меня нет такой цели — критиковать. Мне не понравился исходный код и я посчитал, что он не демонстрирует заявленных целей.

кейс с гвардами по-моему тоже не демонстрирует заявленных целей и есть пример мутного кода (вызванного отсутствием нормального свича в языке?)

остальные кейсы демонстрируют заявленные цели (за исключением тупизма с case _)

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

а вот это уже делать не обязательно

можно заняться критикой — вот например в скале сколько разных ничто — null, Unit, Nothig, None — и это только начало :-)

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

чуть не договорил

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

а вот это уже делать не обязательно *именно на скале*

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

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

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

1. судя по такому названию, как setupSuccessfulAuthResult, тебе лучше записывать их сначала на человеческом языке в виде комментариев (для себя это уже давно понял)

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

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

>похоже, ты в 2 раза ошибся

Согласен, ошибся. Но все равно не 8, а 11 (оператор ||, второй матч не исчерпывающий, +1 за «главный поток»).

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

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

3. параметры функции

тут уже не все так просто

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

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

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

> +1 за «главный поток»

у меня уже учтено, там 7 точек

второй матч не исчерпывающий

???

оператор ||

если бы там были сайд-эффекты (a==0 || c+=d/a), тогда оно бы засчиталось, а щас — нет

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

>если бы там были сайд-эффекты (a==0 || c+=d/a), тогда оно бы засчиталось, а щас — нет

Ну ладно. Тогда 10. :)

Почему эти строки не учтены?

case None => respond(UNAUTHORIZED, «User not found»)

case None => respond(FORBIDDEN, «Unknown authentication scheme: » + user.authScheme)

?

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