Pull to refresh
62
0
Даниил Хритошин@steck

User

Send message
Так всё верно. Проджект менеджер читает отчёт специалиста из QA Кузьмича о найденых дефектах и решает, отправлять ли продукт в продакшен. И тут уже возможны четыре ветки событий:
1) Качество ужасное и идти в продакшен нельзя. Тут влетает Роману, поскольку он не смог выпустить продукт в соответствии с ТЗ в разумные сроки.
2) Качество ужасное, но ПМ решает идти в продакшен. Компания терпит убытки из-за найденых дефектов, влетает, в первую очередь, ПМу.
3) Качество среднее, продакшен, но обнаружилось несколько проблем, не отловленных командой Кузьмича. В этом случае виноват QA, поскольку предоставил неверную информацию о качестве продукта.
4) Качество ужасное, ПМ решает идти в продакшен, софтина выстреливает, все счастливы. Роман и Кузьмич едят бесплатные печеньки на кухне, ПМ катается на новом мерсе.

При разборе полётов (первые 3 сценария) ПМ всё равно влетит, но причины разные.
Да нежно его как-то на видео бьют. Я бы даже сказал, легонечко толкают.
Вот Big Dog на известном видео пинали от души.
По таким запросам, как я понимаю, «детектил», тоже подойдёт.
А под «су%а» ещё больше вариантов…
Пришли к соглашению, что null не является валидным элементом всех коллекций, за исключением IEnumerable<Nullable<T>>. Возможно что-то подправили в решарперовском переопределении свойств. (у них же на всё xml-ки есть)
Точно не помню, что делали, поскольку это было давно и особой проблемы не создавало. Возможно, что я просто не так вас понял.
А я где-то выше писал, что в рабочем проекте такой подход не использую по именно этой причине. Убедить всех людей следовать единому стилю тяжело, контролировать это ещё трудней.
Как сделать изящное решение на С#, чтобы обеспечить контроль использования обеих веток (Value и Null) я не знаю.

Теоретически должно хватить
Maybe<TResult> Map<T, TResult>(this Maybe<T> souce, Func<T,TResult> transformation);
и
T Extract<T>(this Maybe<T> souce, T fallbackValue)
без возможности извлечь значение из но Maybe, но С# не функциональный язык и использовать такое было бы неудобно.

(например методы из EntityFramework и базирующихся на них RIA-сервисы)
Про это уже писали в habrahabr.ru/post/118934/
Так у всех есть та или иная методика, как писать код правильно. И у всех она более или мне работает. =)
Просто мне не понравилось, как dmomen необоснованно обругал один из предложенных подходов.
Maybe увеличивает сложность, не решая задач. Не вижу тут никакой иронии.
То что оно не решает задач исключительно Ваше мнение.

Null не особенный и не объект. Это свойство ссылки.
Null это страшное наследие из C, которое во многих современных языках уже прибили. И да, я не хочу думать над программой в терминах указателей, ссылок и их свойств. Оставьте это ребятам из лагеря плюсов.

Если я могу увидеть объект, то я могу создать новую ссылку на него. Так и делают: var item = mbItem.Value; Новая ссылка, новая головная боль.
Тогда исключительно Ваша проблема, что Вы решили себе создать немного новой головной боли. Я показал как в реальной задаче сделать так, чтобы боли не возникло даже случайно.
А теперь попробуйте сделать тоже самое включив, но в CodeInspection-Settings поставить «When entity doesn't have explicit NotNull attrobute».
Количество потенциальных мест с ошибками увеличится в разы, и возможно, часть из них будет реальна.
ReSharper по по умолчанию корректно работает только в встроенными функциями, на которые у них атрибуты расставлены.
В рабочем проекте у меня настроено считать ошибкой отсутствие [NotNull] или [CanBeNull] на всех публичных методах, пропертях, конструкторах. Этого хватает, чтобы избежать большинства ошибок.
В своих проектах всё равно предпочитаю использовать проверки основанные на типах а не на решарпере.
> Его можно настроить или вызвать, но это не обязанность, а лишь возможность.
Я хотел сказать, что сборщик, это фича (языка, платформы, системы), которая точно так-же позволяет переложить часть ответственности с программиста на машину. Пусть уже встроенная в язык, но фича. И если уж отказыватся от фич типизации, то почему-бы не отказаться и от этой. Видимо <irony> надо ставить…

> Если метод возвращает Item то это будет или Item или унаследовавший тип. Как можно получить что либо еще? Null не тип и не объект, а метка в ссылке. Объекта или нет или он есть и является указанного типа.
Ещё раз повторю мысль из всех комментариев. По умолчанию null это метко. В большинстве случаев мне, как программисту, не хочется проверять исключительный случай, когда объект null. Более того мне кажется неправильным разделение на `один особенный объект` и `все остальные`.
Поэтому предлагается ввести конструкцию Maybe, которая позволит явно указать места, где метка null может появляться, а в остальных местах про неё просто забыть. Таким образом во всех функциях где возможно исключительное поведение (возвращение нулл, как GetItem) ставится Maybe<T>.
В местах где такой возможности нет (метод int SaveItem(Item toSave)) Maybe<T> не используется.
Такой подход позволяет находить проблемы задолго то их появления в тестировании, а следовательно экономить время.

> И я не понял, почему объект должен быть неизменяемым (как я понял, речь об immutable)? Как же мне тогда обновлять репозиторий?
Под объектом я имел ввиду экземпляр Maybe<T>. Класс должен выглядеть как
private readonly T item;
public Maybe(T obj){
if(obj == null) throw new InvalidOperationException();
item = obj;
}
и не менять объект внутри него не при каких обстоятельствах.

Метод же, при использовании map выглядел бы как
public Maybe<Item> SomeMethod(){
return GetMbItem().Map(ModifyItem);
}
Такой вариант написания отловил бы использование ref (конструкции, которою стоит использовать очень осторожно и как можно меньше), сократил бы код, упростил бы понимание.
Невозможно покрыть все скользкие места. Иногда нужно просто писать корректный код,

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

PS: DivisionByZero покрыто в double, где есть две бесконечности и NaN.
Boxing/Unboxing это преобразования. Сохранять или не сохранять тип они не могут. Существование implicit преобразований отдельная тема, но типов оно не меняет.
Сборка мусора, как раз упрощает систему, поскольку забирает ответственность за контролем памяти от клиента. Вариант с Maybe добавляет новый элемент в прогамму и способствует непреднамеренному копированию ссылок.
Сборка мусора тоже добавляет новый элемент в язык. Принципиальных отличий нет. Разве что сборку мусора не отключить в текущей реализации языка.
А так Maybe забирает ответственность за контролем невалидных данных (если следовать контракту, что явно не указанная возможность null — ошибка) с пользователя на компилятор. Задачи одного порядка.

А про непреднамеренное копирование ссылок я вообще не понял. Если Вы про ModifyItem(ref item), то это ад и погибель. Item должен быть неизменяемым. Добавление функции с сигнатурой
Maybe<TResult> Map<T, TResult>(this Maybe<T> souce, Func<T,TResult> transformation);
вообще избавит от большинства проблем.
Простите, а как Вы делаете вывод о количестве ошибок в проекте? Человек привёл весьма эффективную технику, которая позволяет переложить ответственность за NullReferenceException на контроль типов. Как результат — ошибки пропали совсем.
Я сам использую нечто подобное, но в личных проектах. При большом количестве людей соблюдать правила не получается, в результате система начинает разваливаться. Запретить null на уровне компилятора нельзя.

А то кодили на питоне, потом перешли на c# и, удивительно, все ошибки вида "{aaa} object has no attribute {bbb}" пропали. Наверное там столько скрытых ошибок в проекте.
Полностью не согласен. Иначе можно дойти до:
Зачем нам нужна эта противная сборка мусора. Всегда были стандартные средства для ручного управления памятью. Усложнять систему созданием гарбадж коллектора совсем необязательно.

И вообще основной смысл систем со статической типизацией: отловить потенциальную ошибку до того, как код вообще станет рабочим. Вариант с Option/Maybe/Nullable крайне хорош в этом плане. Контракты несколько хуже.

Основная проблема null, в том что он не сохраняет тип. Зачем это нужно хорошо описано в Types and Programming Languages
а на вопрос про pi^2 = 10 я бы ответил, что в таком случае pi было бы равно корню из 10.
Как скучно. Можно было бы предположить, что пи равно минус корню из десяти. И начать рассуждения а том, что получится с пространством, если пи будет отрицательным.
Может получилось бы «вогнать в ступор» собеседуещего.
Не лучше ли тогда отдельно купить плеер? Он весит меньше, играет дольше, стоит дешевле и, в дополнение, не тратит заряд телефона, который может вдруг понадобиться.
Если бы я каждый день смотрел по сезону, то пришлось бы каждый день что-то удалять и что-то записывать.
Записал один сезон сериала в плохом качестве — вот и кончилось место.
Или Вы предпочитаете каждый день что-то удалять и что-то записывать?
По поводу задачки:
Если делить поровну каждый раз на 3 группы, то нужно победить в 2 группах из трёх.
таким образом если для победа в группе требуется
x голосов на y избирателей, то для победы в большой группе потребуется на 3y избирателей.
Самая малая группа: группа из 3х человек.
Тогда получаем что на каждом шаге нам нужно 2к голосов на 3к избирателей.

При к=17, получаем 217=131072, 317=129140163, что больше чем число избирателей. То есть одного процента точно хватит чтобы победить в выборах.
Вроде про выборы уже всё сказано в Теореме Эрроу. Провести честно выборы невозможно математически, есть только приближения.

Information

Rating
Does not participate
Location
Matosinhos, Porto, Португалия
Date of birth
Registered
Activity