Pull to refresh
12
0
Антон @Ithilgwau

User

Send message

Я не понял, а как повторы-то исключается, если нигде не фигурирует ID участника?

Хороший простой ответ. Автору следовало это расписать, а не писать "Т.е. мы установили, что ... он максимум состоит из 6 цифр." мелким шрифтом, как что-то само собой разумеющееся. Я тоже при прочтении завис на этом моменте: "Когда это мы установили?"

Я C#-backender, которому приходится быть fullstacker'ом, и эта статья для меня - то, что нужно. Респкт автору. Отличное понятное изложение, грамотный язык. А это редкость...

Отлично, рад что мы поняли друг друга ;) Просто, глядя на этот конкретный пример, у меня зародились подозрения о слепом использовании каких-то подходов (о чём я писал). Но если это делается с умом, то это конечно другое дело. Будем ждать апдейта и новых статей, и успехов Вам в разработке!

В общем, как писал SergeyT:

Помимо пользы, от паттернов проектирования может быть и вред. Бездумное и неразумное использование любого даже самого полезного инструмента или технологии приведет к «абсурду и коррупции». Сколько раз вы сталкивались с проблемой “overengineering-а”, когда для реализации простой концепции использовался десяток паттернов проектирования? В общем, это очередной пример того, что прагматизм и здравый смысл, как всегда является лучшим выбором, и паттерны проектирования – не исключение.

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

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

Лично я бы преобразовывал суммы сразу при общении с этой другой системой в decimal, только и всего. И удалил бы напрочь «long kopeks» из проекта, как кошмарный сон, чтобы вот вообще никаких следов это безобразия не осталось :)

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

Эмм… А «концепция»-то в чём заключается? Чем вот по сути эта структура отличается от long? Умножением и делением на 100? Это и есть та «концепция», которую непременно надо куда-то инкапсулировать?

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

Не объектов, как объектов, которые имеют поведение, а объектов, которые являются структурами данных

Ну, лично в моём проекте там полно поведения :) Некоторые вещи прекрасно решаются интерфейсами и методами расширения. Я не идеализирую EF, ни в коем случае. Там огромная куча недоработок…

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

Подчёркиваю, любой паттерн создан для решения каких-то проблем. Если этих проблем нет и не предвидится, любое их использование — это дорога в ад. А если проблема есть, то надо сначала подумать, какими способами можно её решить, собственной головой. Умный не тот, кто прочитал много книг. А то, кто умеет перерабатывать информацию и генерировать новую (если она конечно полезна). Тот, у кого развита интуиция за базе собственного опыта. Какие-либо авторитеты и совершенно ненужные знания обычно не помогают, а вредят интеллектуальному развитию и личному росту. Вот ей Богу, если бы тот разработчик, которого я упоминал, не прочитал ни одной книги, он бы написал намного более качественный и понятный код, а главное — научился бы думать.
На самом деле, даже обёртка над decimal может пригодиться, если понадобится унифицировать обработку разных по смыслу данных. Самый простой пример — ToString():
var items = new object [ ] { someMoney, someOtherValue };
foreach (var item in items) Show(item.ToString());

Если бы в Вашем примере был реализован ToString(), в нём был бы хоть какой-то смысл. Хотя, и то этот смысл сомнителен, т.к. необходимость ради одного ToString реализовывать кучу операторов (для превращения Money в полноценный decimal) — это большой вопрос, и зависит опять-таки от контекста, в роли которого выступает проект.
Money.FromRubles(10) гораздо лучше чем decimal a = 10m;

Есть структура, которая делает код более читабельным

Да Вы, верно, шутите? По-Вашему это более читабельно? Дело не в согласии несогласии, а в фактах. Сколько человек на Земле знают про Вашу структуру Money? И сколько человек на Земле знают про тип decimal? Глядя на запись «Money.FromRubles(10)» у меня сразу же возникает куча вопросов: а как эта структура будет хранить данные — с какой точностью? А не конвертирует ли она, случайно, рубли во что-то ещё в этой ф-ции? А смогу ли я использовать её в мат. выражениях? А насколько она производительна? И т.д. Вы сами посмотрите на этот код через полгодика и будете судорожно пытаться вспомнить, зачем Вы этот Money вообще ввели.

Представьте, что Вы открыли чужой код. Что для Вас будет более читабельно — вот это: «new DateTime(2015, 4, 5)», или вот это: «5.April(2015)»?

Ну, так тот разработчик сделал глупости, вероятно

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

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

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

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

Ну, или же, оборачивайте в структуры все подряд: string'и, int'ы, float'ы. Оберните заодно и все объекты Framework'а. А что, вдруг пригодится? ;)
Обратите внимание, что конструкторы закрыты

Без разницы. Money.FromKopecs — ничем не лучше.

Если вы напишите класс ZipCode, то он станет оболочкой над string и что дальше?

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

Где у Вас проверки на корректность как в случае в ZipCode?

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

Помнится, я работал с одним молодым разработчиком, который слишком любил читать «умные книжки». И однажды, когда мне пришлось, работать с его кодом, я пришёл в тихий ужас, который у меня не проходил несколько дней. Грубо говоря, у него для деления на 100 использовалась даже не одна структура, а целая иерархия из шаблонных классов. И практически каждый паттерн, который он применил, был применён совершенно не по делу, что сделало его код нечитаемым даже для него самого. И весь код был выброшен в помойку.

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

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

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

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

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

Если Вы решите хранить и оперировать деньгами в decimal и перепишете этот класс соответствующим образом, чем он станет? Оболочкой над decimal.

И поверьте, если у Вас в системе фигурируют суммы в «long kopecs» (что изначально являлось недоработкой проектирования), то запись «decimal money = kopecs/100» будет гораздо очевиднее незнакомому с вашим кодом человеку, чем «var money = new Money(kopecs)», т.к. с Вашим Money он вообще не знаком, и ему придётся заглянуть в него и ужаснуться.

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

А до тех пор лучше заняться избавлением проекта от «long kopecs», а не потворствовать этому. А эта абстракция, раз уж она уже есть, пусть существует в виде оболочки над decimal, может, когда-нибудь и пригодится…
Да по сути, в любом случае на общую производительность, судя по тестам, 4-канальность не влияет… Поэтому и в DDR4 я особого смысла не вижу, если latency будет той же…
Сейчас пошукал в инете и выяснил, что всё-таки не будет он на Z87 работать… Получается, что выбора только два: покупать сейчас LGA2011 или ждать год. Иначе не будет никакой возможности для роста.
В том-то и дело, что к сожалению, Z97 выйдет только во второй половине 2014-го, насколько я читал… Надеюсь, Broadwell хотя бы не откажется работать на Z87…
Да просто я выбираю сейчас между LGA1150 и LGA2011… И задумался: а стоит ли ждать DDR4, если я сейчас возьму LGA2011…
Ну вообще, я другие результаты видел… В синтетике пропускная способность выше почти в 2 раза, как и должно быть…
А мне вот интересно, что будет лучше 4-канальная DDR3 на LGA2011 или 2-канальная DDR4? Мне сейчас как раз апгрейд светит, и получается, что если это будет равносильно, то можно преспокойно продолжать сидеть на DDR3 ещё ооочень долго…
Вот когда мне с такими задачами приходится сталкиваться, я их решаю на ура. И эту решил, без спойлера и без бумажки. Но ни на одном собеседовании я подобное решить не способен. Не учитываются психологические факторы, различные у разных людей. К тому же, на практике всё, что Вы перечислили, встречается с вероятностью 0,0000001%. А паттерны, кстати, лично я не очень уважаю. А уважаю умение думать головой и знание тонкостей языка. Только вот заставлять думать головой на собеседовании — это извращение, потому что у человека даже в течение дня IQ может прилично скакать. Смотреть надо по опыту и по делам, а не делать выводы из решений подобных задачек.
Спасибо, не знал про него, поправил.
Воспользовался Вашими пожеланиями и убрал из текста статьи всё касаемо вариативности, чтобы не запутывать лишний раз (только в коде оставил). Но кое-что дописал (добавил ещё один подход). Теперь вроде всё в полном объёме и всё по делу :)
Дописал статью, добавив туда «Адаптер». Только убрал из вашей реализации наследование Vector и IVector от IReadOnlyVector, т.к. в этом случае становится возможным беспрепятственно передавать Vector и IVector в методы, которые принимают IReadOnlyVector, без вызова AsReadOnly(). А такое я уже описал в пункте 2. В общем, спасибо в любом случае, приятно было подискутировать.

Information

Rating
Does not participate
Location
Россия
Date of birth
Registered
Activity