Если аттрактор и друг это типы из разных сборок, то возникает циклическая зависимость между сборками.
Понял вас. В принципе вы правы. А чтобы не было циклической зависимостей (но не только), такие зависимости обычно принято выносить в отдельную сборку (какую-нибудь «Contracts») в виде интерфейсов, даже рекомендуется как часть SOLID принципов — DIP. Тогда можно будет без проблем определять правила на интерфейсах.
Но спасибо вам, что подсказали вариант доработки аналайзера, для случаев если не хотим это делать. Решается просто: например, добавить для OnlyYou атрибута еще один конструктор с таким использованием: [OnlyYou("T:MyFriend",...)] Ибо аналайзеру, в принципе, достаточно лишь имени типа.
Как я понимаю, мы о разных "трех не" говорим.
Пожалуй, оставим это правило в плюсах, чтобы не уводить дискуссию в сторону. Это своя тема.
И ассоциация с плюсовыми френдами только путает. Обсуждаемый псевдо-модификатор это не френды (плюсовые френды критикую в статье), а это коротко говоря: public с правилами.
И следующая ваша цитата, мне кажется, продиктована этой путаницей с плюсами:
Опять же... если кто-то, что-то "видит" - он имеет полное право за это "дергать". И - скажем так - "прикладная задача проектирования" сводится к "надо сделать так, чтобы каждый видел только то, что ему можно дергать". А вы - буквально - говорите "а давайте на это всё забьем" :-)
По примерам с nested классами и вообще о nested решениях: Во первых попадаем под то проклятие — «эксбиционизм» плюсовых френдов (если используем именно inner класс как есть). Не можем сделать один и тот же класс как nested сразу 2-х классов Менее селективно. Не всегда правильно загонять класс в nested (по моему опыту необходимости в элвис-модификаторе возникала в таких классах, которые ну совсем не годились чтобы из них делать nested пары).
Приведу такой сравнительный пример:
Скрытый текст
namespace NestedTest
{
class Me
{
private string _veryConfidentialValue = "top secret";
private void Method1() { }
public void Method2()
{
var friend = new Friend(); // ok
friend.SomeMethod(); // ok
}
public class Friend
{
public Friend() { }
public void UseMe1(Me me)
{
me.Method1();
var getAnySecret = me._veryConfidentialValue; // ok
me._veryConfidentialValue = "hack any secret"; // ok
}
public void UseMe2(Me2 me2)
{
me2.Method1(); // err
}
public void SomeMethod()
{
var me = new Me();
}
}
}
class Me2
{
private void Method1() { }
}
class Other
{
public void UseMe1(Me me)
{
var friend = new Me.Friend(); // ok
friend.SomeMethod(); // ok
}
}
}
namespace EATest
{
class Me
{
private string _verySecureValue = "top secret";
public Me() { }
[OnlyYou<Friend>(nameof(Friend.UseMe1))]
public void Method1() { }
public void Method2()
{
var friend = new Friend(); // ok
friend.SomeMethod(); // err
}
}
class Me2
{
public void Method1() { }
}
class Friend
{
[OnlyYou<Me>]
public Friend() { }
public void UseMe1(Me me)
{
me.Method1(); // ok
var getAnySecret = me._veryConfidentialValue; // err
me._veryConfidentialValue = "hack any secret"; // err
}
public void UseMe2(Me2 me2)
{
me2.Method1(); // ok
}
[OnlyYou<Me>(nameof(Me.Method2))]
public void SomeMethod() { }
}
class Other
{
public void UseMe1(Me me)
{
var friend = new Friend(); // err
friend.SomeMethod(); // err
}
}
}
Ну вы чего?! Через neasted объявляются агрегаты (сильно упрощая - интерфейсы), которые потом используются для "сборки" того, что вам нужно где-то "во вне".
Насколько вас понял, под агрегатами (интерфейсы) имеете ввиду определять интерфейсы (или (абстрактные) классы) как nested с реализацией доступа с приватному функционалу внешнего, а потом где нужно наследоваться от этих интерфейсов. Т.е. ровно то, что я описывал в разделе статьи «Через интерфейс» (очевидно, интерфейсов может быть сколько угодно). Ну а далее предложил и другой подход в виде псевдо-модификатора.
Спасибо! Прежде всего отмечу, что, имхо, польза может быть особенно в проектах с большим, сложным внутреннем API, где важно строгое соблюдения контрактов/бизнес-логики.
Сборок может быть сколько надо, нет ограничений, главное чтобы аналайзер был ко всем ним подключен, или подключен хотя бы пакет с атрибутам, если в какой-то сборке функции аналайзера не нужны, но атрибуты используются (если все в одном сольюшене, то предлагался Directory.Build.props).
Например, достаточно "представить", что "аттрактор" и "друг" это типы из разных сборок. "Лишняя" связь тут же станет очевидной. Нет?
В разных они сборках или нет, в любом случае, они знают друг о друге (иначе как декларацию декларировать?). Знают и используют (уже имеем связь), если же не используют, то писал о варининге и TODO (или, наоборот, можно сказать, UNDO индикаторе, если оказался просчет в начальном проектировании).
Вот как раз "через интерфейс" исходная задача решается "с точностью до наоборот". В том смысле, что исходная "сущность" - мутабельная, а через реализацию интерфейса предоставляется readonly проекция. Нет? При таком подходе, "грануляция" доступа - пока отбросив её ценность - органично "схлопывается" до агрегатов. Оно может быть и выглядит громоздко на синтетике, но смотрится вполне себе нормально и логично (отбросив, опять же, всё остальное, что можно "предъявить" такому агрегату).
Исходная сущность (класс Me) внешне как раз не мутабельная (readonly), а "через интерфейс" предоставляется строго избирательная "проекция" с доступом к внешне скрытым или/и readonly мемберам. Простите, про агрегацию, плохо вас понял. Имеете ввиду inner/nested классы (когда inner класс может получать доступ к закрытым мемберам outer класса)?
Про френды в C++ уже который раз пожалел, что вообще упомянул, они лишь начальная ассоциация, и, смотрю, каждый раз, «вызывают на себя огонь». Вот их можем отбросить, они лишь путают в понимании. (а правило "три не" в плюсах, хорошее правило, если бы еще все его знали и использовали, это ведь только благое пожелание, а не запреты на уровне синтаксиса языка).
Помимо основного тела статьи, в «Приложении» сделал много примеров задач с возможным применением, обоснованием зачем. Думал достаточно (можно попробовать их решать другими методами, не спорю, и тогда уж сравнить что будет проще/лаконичнее...).
Когда вы говорите про "торчащие нитки", вы вообще о чём?
Про «торчащие нитки» (образное выражение), за которые могут дергать (т.е. использовать эти нитки-мемберы/классы: вызывать методы, сеттить свойства...) все (ну почти все с учетом более глобальных модификаторов) в том числе и те кому не желательно согласно контракту (это иллюстрировал в примерах).
Складывается ощущение что вам кто-то строго запретил пользоваться internal (и его производными) уровнем доступа и использовать neasted иерархии.
internal и nested не дает той гибкости и селективности, как данный модификатор. internal работает «по площадям». nested не всегда возможен (а если нужен как nested сразу в нескольких классах? а если нужен «взаимный» nested?) и удобен, и он получает доступ сразу ко всем приватным мемберам outer класса (фактически как в плюсах в варианте не function friend), что не есть хорошо.
Про оценку ценности тут, конечно, пусть каждый сам приценяется, насколько ему интересен данный функционал (сугубо лично мне интересен).
Withkittens Спасибо за профессиональный пост! Вы правы, есть разные решения, которые не умоляю. Да, и в Rust есть, что хотелось бы иметь и в C#. Предлагаемый вариант, имхо, все же гибче, селективнее описанных вами подходов. В примерах в «Приложении» попытался показать применения. Возможно дело привычки (всегда кажется лучше и проще то к чему привык). Наверное пристрастен, только, имхо, просто поставить на мембере или классе/интерфейсе атрибут с вполне очевидным смыслом (Только Ты <T>), не так уж напряженно. Вот вы, как понял, профи и в Rust, вот там, имхо, действительно сложные вещи (как минимум за себя скажу — ломал мозги когда изучал).
Ну почему "прибиты гвоздями", вот новые появляются как тот же file модификатор. И, конечно, в CLR не лезу, кто же мне позволит? Ну назвал модификатором инструмент, который фактически выполняет функцию модификатора. Вы не согласны с названием, понял вас, уважаю ваше мнение (говорю, даже ни одного минуса не поставил вам в отличии от вас, после моих ответов). Смысл дальше спорить? (и не я его начинал, лишь вежливо отвечаю вам)
Потому как этот атрибут фактически и выполняет функцию модификатора доступа, конечно, нового модификатора не входящего в стандарт. Поэтому счел возможным назвать как модификатор. У нас с вами дискуссии по названиям. Имхо, названия не столь важны как суть, предлагаю не продолжать их.
Увы, авторитетных доказательств что именно в C# тернарный оператор называется еще и Элвис оператором вы не привели. Уважаю ваше мнение и право называть что-либо как вы хотите, но пока тот же гугл не разделяет его. Даже не минусую ваши посты (в отличии от вас).
В статье же речь не об операторе, а о модификаторе, так что какая путаница?
И, поверьте, не «лезу в бутылку», готов признавать свои ошибки (буду только благодарен если укажите на них, ставлю за них лайки, как тут ниже для chegeras и вам готов поставить), готов узнавать что-то новое. Просто пока не понимаю вас.
И опять замечу, что речь в статье о C#, не о Kotlin. В C# именно вот так ?: одной строкой вообще нет такого оператора.
На счет "?:" не встречал чтобы называли его "Elvis operator". Классический Элвис-олератор, как верно далее пишете, это "??" (также как и "?.", тоже относится к Элвис семейству операторов).
В каком-то смысле модификатор и защищает, только не от NullReferenceException, а от нарушения бизнес-логики/контракта. Если бы не было «Elvis оператора», то наверное и не подумал так назвать модификатор, а так дорога уже проложена, считайте традиция, да и для «маркетинга», имхо, хорошее название (в кавычках, потому как какой маркетинг при MIT лицензии).
Как это принято, чтобы продемонстрировать концепт, для ясности приводится самый простой пример. И, конечно же, для таких примеров могут быть альтернативные решения, иногда более сложные решения иногда менее (да всегда есть альтернативные решения, более того, даже тот же C++ можно было не изобретать, ведь все задачи можно и на C решать — вопрос простоты/удобства). В реально жизни же такие демо-примеры — редкие исключения. И зачем, кстати, в стандарте C++ есть friend-ы? Вот, Stupid люди, ввели для несуществующих проблем.
было бы проще сделать абстрактный класс с protected полем и унаследовать оба от него.
Во-первых: а что если какой-либо или сразу оба класса уже имели базовые классы, так что для нового базового абстрактного класса уже не было бы места? (как знаем, в C# нет множественного наследования в отличии от плюсов)
И как уже писал в других комментах, этот инструмент может быть особенно полезен для программ со сложной логикой (там все места обычно заняты), а не «линейных», типа где почти лишь DTO-шки, ORM-отмаппенные классы из дата-сетов + шаблонные контроллеры созданные IDE для вас. Боюсь, что недоумение «зачем это нужно?» от некоторых здесь, и связано с тем, что люди привыкли заниматься такими шаблонными задачами (и это реальность почти всех разработчиков, сам большинство таких задач и решаю, но скоро AI вытеснит программистов из шаблонных задач). Это инструмент для сложных задач, для «ювелиров» настраивающих сложный часовой механизм vs «слесарей» занимающихся рубкой метала где инструменты это молоток и зубило.
Во-вторых: пусть не «во-первых» (т.е. место под базовые классы все же есть), и если правильно вас понял, предлагаете:
abstract class Base { protected decimal Rubles; }
class Me : Base { }
class MyFriend : Base {
public void AcceptMoney(Me me) {
decimal half = me.Rubles / 2; // error
me.Rubles = half; // error
Rubles += half;
}
}
Увы, компилятор не согласен (2 ошибки компиляции).
Если же поле определить как:
internal protected decimal Rubles;
То оно уже будет доступно и всем другим классам в проекте, а не только наследникам Base.
Как вариант решения этой задачи без атрибутов (решение более сложное + с недостатками оговоренными в статье) — см. пример с Me.IFriend интерфейсом в статье.
создаём не очевидные зависимости и раздуваем код сложно читаемыми (по крайней мере для стороннего программиста) атрибутами и псевдонимами.
Вы действительно считаете, что добавить ВСЕГО ОДНУ СТРОЧКУ с атрибутом и означает все что вы тут написали? Одна строчка:
[OnlyYou(typeof(MyFriend), nameof(MyFriend.AcceptMoney))]
public decimal TakeMyHalfMoney()
И что, разве через определения базовых классов, наследования для каждого, создания всей этой иерархии зависимостей... разве код уже не раздуваем, не делаем сложно читаемым (vs ясного и лаконичного OnlyYou атрибута одной строкой)?
А причина почему в C# нет friend не функциональность, а скорее безопасность, это нарушает контракт private и ломает гарантии, в том числе для JiT
Если внимательно почитаете статью, то найдете, что как раз это критикую в C++ friend-ах. Хотя friend-ы вполне себе входят в стандарт C++.
Как уже отмечал, имхо, при использовании любого инструмента нужно пользоваться головой, ибо всегда, даже самый хороший инструмент можно извратить, довести до абсурда в его применении. Это касается и инструментария в статье. По моему опыту, даже в сложных задачах, применение elvis-модификатора в среднем требуется к 1 методу на 100 классов, а вовсе не безбашено лепить на каждый метод, каждого класса.
Важно: Как писал и в статье и во многих комментах, предложенный подход уже не совсем аналог плюсовых friend-ов. Другой инструмент, избавленный от важных недостатках плюсовых friend-ов. Можно сказать, это вообще не friend-ы. Они были лишь одной из мыслей-истоков, аналогией от которой оттолкнулся.
Правильнее говорить о новом, более селективном модификаторе доступа (elvis-модификаторе). Модификатор не открывает приватные члены (не нарушает private контракт), а делает селективным доступ к публичным. Например, вот где (помимо статьи) более подробно говорю: https://habr.com/ru/articles/961264/comments/#comment_29068288
А private контракт ломает разве что рефлексия. Аналайзеры же (тем более без фиксов как здесь) в принципе ничего не ломают, а лишь выдают ошибки/предупреждения при компиляции. Более того, если программист сам явно не добавит elvis-модификатор, то аналайзер никак себя и не проявит, как если бы его и не добавляли в проект.
Чтобы не путали с friend-ми даже возникло желание переименовать проект в ElvisAnalyzer (+ маркетинг хороший, хотя все бесплатно, все для вас дорогие, хоть бы кто спасибо сказал, кроме одного, только ругают и минусуют).
---------------------------
Спасибо вам большое, что хоть задали технические вопросы, а то, к сожалению, тут скорее заняты художественным аспектом (некоторыми аспектами «одежки» статьи, а не сутью) и моей личностью, даже не приводя конкретные аргументы.
Впрочем, и вы без наездов на мою Stupid личность не обошлись :) (хотя, реально, бывает туплю) Но уже и такому рад — «на безрыбье и рак рыба», коль без наездов никак (если что, просто поговорка, а не обзываю вас «раком», уважаемый коллега).
Так давайте и обсуждать техническую часть, а не художественную. Рассчитывал, что именно-именно так и будет. Только и только «за» и руками и ногами.
Вместо этого в основном переход на личности (причем «заметьте, не я это предложил» — такую тему, или мне стоит быть польщенным к такому вниманию к моей личности?).
Да, есть у меня свои индивидуальные особенности. И народ за них зацепился (а мне вот не нравиться как мой сосед одевается, но тем не менее хорошо общаюсь с ним, никогда не поднимая тему его одежды). Их можно либо попытаться понять (и даже вдруг тут открыть для себя что-то новое, моим друзьям/знакомым — нравится), либо абстрагироваться от них. Тем более в технической части статьи этого немного. Ну либо, на самый худой конец, вот так как сейчас... хорошее тут слово было в постах, а вот, нашлось — «наезжать» (можно позаимствую?). Тоже вариант и ваше право.
Т.е. что же это получается? По факту многие люди здесь показали, что им гораздо важнее художественная, а не техническая часть? Одежка, а не внутренность?
Знал бы что будет такая неожиданная реакция — конечно по другому бы написал, для вас дорогие коллеги, сломал бы себя (пусть и поется в песне «Но не смотри, не смотри ты по сторонам, Оставайся такой, как есть, Оставайся сама собой...»).
Это первая (и похоже последняя) моя статья, о чем писал в самом начале и просил «Пожалуйста, позаботьтесь обо мне». Что же, так вот она какая забота («вот он какой северный олень»), Ваше право.
P.S. И может быть если бы вы чуть лучше разбирались в людях (простите, если ошибаюсь) то знали бы что часто люди шутят не от хорошей жизни. Жизнь боль и не только своя, но и близких. А юмор он помогает держаться. Если у вас все прекрасно, то реально рад за вас (всегда молюсь чтобы Господь и дальше хранил счастливого человека которого вижу).
Ну, да, извините, что уделяю вам свое время, внимательно читаю ваши посты и стараюсь максимально полно ответить вам. Пожалуйста, не будьте к себе строги, уверяю, «ведь вы этого достойны!». Так что какие наезды? Извинения и благодарности. Хотите знать что такое наезды? Тут далеко ходить не надо — есть, есть тут характерные посты, можете перечитать на досуге, если забыли.
«ИМХО», конечно было в одном вашем хорошем посте, на который, имхо, хорошо ответил. Только отвечали то вы мне, а потом я вам на содержание другого поста, гораздо ниже. Потеряли контекст? Тот ваш пост, который уже, как бы это помягче сказать чтобы вас не обидеть... Ай, не буду говорить, не хочу вас обижать, дорогой коллега.
А что с оправданиями не так? Не имею право отвечать? А кто тогда защит меня бедного детсадовца от взрослых и таких невообразимо умных дядей? Даже вот очень известная фраза гласит: «...Вы имеете право на адвоката. Если вы не можете позволить себе адвоката, он будет назначен вам бесплатно». Тогда требую бесплатного адвоката! Пусть он меня оправдывает, а я буду «хранить молчание».
Вам дали пересоленную еду. Вы говорите: невозможно есть, она очень-очень солёная, соль даже скрипит на зубах. Но вам отвечают: вы просто глупый, ленивый, поверхностный, не разбираетесь в кулинарии, и вообще вот вам две, даже три часовых лекций на тему, почему вы должны поверить, что это шедевр.
Научитесь, наконец, принимать критику, как взрослый человек. Ваши кирпичи текста в комментариях не добавляют ясности, а только ещё больше усугубляют. Вы не обязаны с каждым соглашаться, но обвинять окружающих в лени, тупости, посредственности только потому что не оценили ваших художеств — хамство, не иначе.
Где "ИМХО" то? Или не только у меня проблемы?
И вам что завидно, что на вежливый положительный ответ — вежливо положительно ответил? (если так, то, пожалуйста, не надо, читал, что согласно статистики, зависть — основная причина депрессий в США, поберегите себя).
Впрочем и вам и всем вежливо отвечаю (так что, еще раз, пожалуйста, не приписываете мне своих мыслей). Более того, даже вам вот ниже постом немного отлизаблюдил (в вашей терминологии).
Также благодарю вас, что отслеживаете и собираете библиографию моих постов (вот еще раз вам отлизаблюдил). Не хотите стать моим летописцем?
Коллега, а вы не находите, что вы мне тут столько всего наговорили, столько своих непрошенных оценок навешали, что тут можно долго разбирать всякие ваши issues, давая встречные оценки (может даже «букетик» issues? как это принято мягко называть в английском, ведь у них всегда «no problem», это только у меня по вашим словам серъзные problems). Но нет, так никак не могу, ведь как и все воспитанные люди, понимаю, что без запроса от собеседника самому давать ему оценку крайне не этично. В свою очередь, извините, если где-то невольно что-то проскочило.
И вот что мне странно: у меня есть сейчас время (ведь ~ «ленивые часов не наблюдают»), и я с удовольствием общаюсь с вами (получаю «роскошь человеческого общения»). Вдруг меня (глупого конечно), умные и взрослые дяди научат не только плохому, но и чему-то хорошему (и да, есть уже результаты/выводы, спасибо всем!). А вам вот все не нравится, но вы упорно продолжаете общаться (на кактусах тренировались?). Все-таки какие мы все разные и как же это интересно!
Некоторые образы понравились, реально хороши (не ai случайно? просто похоже). Единственное, уж очень, очень, имхо, гипертрофировали в попытке сарказма. Чашка кофе с ложной сахара и чашка сахара с ложной кофе - чувствует разницу?
Но не настаиваю, не осуждаю «вы художник — вы так видите». У меня свое мнение, у вас свое. Или считаете это ненормальным?
Спасибо за ваше мнение, оно очень ценно для меня! И после этого вы говорите, что не воспринимаю критику? :)
Уважаемый, очень взрослый человек, стесняюсь спросить: а на критику можно отвечать, просить аргументировать? Или только в духе «ему ссут в глаза — а он божья росса». Ибо как можете заметить она тут очень лаконична, без аргументации, порой просто фразой-эмоцией, и если бы она была применена к вам, то возможно (возможно, не настаиваю конечно), то вы бы ее, наверное (наверное) как раз и назвали детским садом.
Как же мощно вы меня припечатали, просто намотали на гусеницы: «вам отвечают: вы просто глупый, ленивый, поверхностный, не разбираетесь в кулинарии». Позвольте, ну не совсем все же верно (хотя иногда и бывает что туплю) и это не мое мнение, «у меня и справка есть» (и совсем не об окончании «кулинарного техникума» и совсем даже не на двойки, а с точность наоборот).
«Ленивый»? (хм, труд проделал огромный — реально, + тут, стараюсь, каждому очень-очень развернуто отвечаю, задаю вопросы...). Признали щедевром? Где на такое надеялся? Пожалуйста, прошу, не надо за меня выдумывать, ведь это справедливо считается очень не этичным. В таких случаях просто спросите меня, если хотите знать что реально думаю (а не что вы думаете, что я думаю, что я думаю).
Да и отвечают не все как вы, есть тут совершенно другие мнения.
Замете, остаюсь с вам в рамках вежливого общения, несмотря на откровенное хамство.
А теперь можете ставить свой очередной минус (ну если захотите, конечно, ведь не вежливо указывать другим что им делать, так что, конечно, не настаиваю).
Спасибо Огромное! Ваш комментарий особенно ценен на фоне превалирующего непонимания. Почитав иные комменты, считаю, что люди просто не поняли материал статьи.
А некоторые, похоже, даже не потрудились дочитать (но осуждают). Особенно первые 2 мгновенных минуса, сразу, в ту же минуту, после публикации. Возможно это были северо-корейцы, которые прочитали лишь первый абзац со ссылкой на цикл о Южной Кореи (но ведь тоже не потрудились прочитать цикл, ибо там совсем не воспеваются порядки южан).
Написал, имхо, полезный инструмент, выложил в открытый доступ, берите пользуйтесь на здоровье, если кому понадобится.
Статью с любовью запилил, стараясь ее сделать не скучной, чтобы люди не засыпали на бубнеже о технических деталях, разбавил шутками юмора. Хотя это больше про небольшие вводную часть и заключение, в которых традиционно вполне допускаются лирические ноты. Основная же часть, имхо, должным образом (как многие требуют) скучная.
Даже не ожидал, что это будет такая огромная работа (причем все «безвозмездно, то есть даром» от чистого сердца).
И, думаю, конечно, тут каждому будет по человечески обидно. Сижу-гадаю: «что же вам, собаки, еще надо-то?!» Ладно, извиняюсь (пред теми кто отнес на свой счет, не понял юмора, цитаты) — собаки зачеркиваю, это я сгоряча, на эмоциях. Хотя «собака — друг человека», так что вполне в рамках тематики статьи :)
Настолько в когнитивном диссонансе от «ожидание и реальность», что, думаю, уже никогда здесь больше не решусь написать что-либо еще (хотя идей достаточно).
Так что, еще раз, моя вам искренняя благодарность за понимание, умный, образованный, с хорошим чувством юмора человек.
Это поясняемая цитатами и пословицами — доказательная логика: почему число 100, а не любое другое как могли бы недоумевать, и почему надо делится с другом, и почему именно «на лапопам». Чтобы не было вопросов что тут за цифры и действия такие взятые с потолка или с бодуна. Так сказать описание предметной области, которая будет моделироваться программой. Ну и постарался сделать это не скучно. А без цитат, ссылок-отсылок в серьезных изданиях так вообще не примут статью :)
По идее такие описания должны восприниматься влет, легко и приятно, как хорошо знакомые и ярко-выпуклые образы, легкими мазками рисуя в воображении читателя живую «картину маслом» (эх, вот опять не удержался от цитаты). Если же спрашиваете: какие ключи, рубли, квартиры, тумбочки. То значит можно сделать вывод, что не находитесь в классическом русском контексте пословиц, мемов, литературной и кино-классики. Вот с этим ожиданием от читателя возможно и промахнулся. Переоценил народ в этом плане.
Хотя это больше про небольшие вводную часть и заключение (как уже говорил), в которых традиционно вполне допускаются лирические ноты. Основная же часть должным образом (как многие требуют) скучная. Ну а редкие вкрапления юмора... так в чем проблема просто пропустить их, если этот юмор не понятен? (ну или у меня он такой не смешной или слишком требовательный к читателю, эх, а ведь старался веселить, т.е. вызывать положительные эмоции).
Честно говоря даже верится что вот это было непреодолимое препятствие, имхо, даже одних примеров кода, которыми постарался обильно снабдить статью, достаточно. Больше похоже на то, что некоторые просто не поняли (поленились) материал статьи, об этом говорят и некоторые из их постов (развернуто отвечал на их все).
По моему опыту не так уж и редко для задач со сложной логикой. Если писать к-л типовой проект, бэкэнд рядового интернет магазина какой-нибудь, то там, да, все более-менее линейно. Другое дело, когда задача со сложной логикой.
Как говорил в статье, следуя ФП дао-пути, всегда так стараюсь выстроить систему классов приложения, чтобы классы в идеальном случаем имели только readonly публичные свойства. Увы, как раз для «нелинейных» задач это не всегда просто удается (а если делать не просто, то обычно уж слишком не просто, непроизводительно, не стоит свеч). Некоторые классы оказываются семантически связанными. Какие-нибудь пары например, при работе одного класса-обработчика необходимо скорректировать некоторое свойство в другом. Но в проекте еще очень много классов, которые видят и читают это свойство, этот класс. Поэтому только ради одного кейса открывать его для всех (public { get; set; }) совсем не хочется.
Особенно в больших, командных проектах иногда видел, что чуть ли не все свойства (надо - не надо) имеют публичные get-set. Вот смотришь на миллион таких классов (особенно на чужие, да и на свои сколько-то времени спустя) и чешешь репу — да где же только в этом огромном коде с миллионом классов и миллионом мемберов в них (ладно, не буду вас цитировать — ограничимся хотя бы 1000) не треплют эти свойства? Напоминает пресловутый антипаттерн глобального состояния, только, имхо, хуже, ибо это состояние, размазано по массе классов и попробуй разберись, как оно меняться, если каждый может изменять каждого. А вот если все неизменяемое, то все куда-куда упрощается, намного проще понять логику. И описываемые в статье инструменты позволяют приблизится к этому идеалу.
У меня в проектах практически все классы неизменяемые. Имеются только очень выборочные исключения для некоторых мемберов, которые открыты, но не тысячам других классов, так что они были бы способны их «матросить», а только одному/двум (intellisense же при большом числе классов с их массой мемберов в каждом тут слабо помогает). Смотришь на них и все прозрачно, видишь явную логическую связь — не тысячи возможных нитей-связей, за которые могут все дергать, а одна/две явно прописанные.
прокинуть доступ через интерфейс/статику/вложенность
ну да, про этот как раз в первой половине статьи и писал (см. Me.IFriend)
попахивает нарушением инкапсуляции.
Про инкапсуляцию так бы сказал (собственно писал про это): не нарушает ее, в скорее дополняет еще одним инструментом. Вводит еще один, можно сказать, модификатор доступа, более селективный модификатор (elvis модификатор). И лично мне нравятся такие тонкие инструменты — как инструменты ювелира vs инструменты слесаря, ими уже можно всякую тонкую, так сказать, «часовую механику» налаживать, а не только рубить метал зубилом с молотком. Яйца фаберже vs рессоры от трактора беларусь :)
Понял вас. В принципе вы правы.
А чтобы не было циклической зависимостей (но не только), такие зависимости обычно принято выносить в отдельную сборку (какую-нибудь «Contracts») в виде интерфейсов, даже рекомендуется как часть SOLID принципов — DIP. Тогда можно будет без проблем определять правила на интерфейсах.
Но спасибо вам, что подсказали вариант доработки аналайзера, для случаев если не хотим это делать.
Решается просто: например, добавить для
OnlyYouатрибута еще один конструктор с таким использованием:[OnlyYou("T:MyFriend",...)]Ибо аналайзеру, в принципе, достаточно лишь имени типа.
Пожалуй, оставим это правило в плюсах, чтобы не уводить дискуссию в сторону. Это своя тема.
И ассоциация с плюсовыми френдами только путает.
Обсуждаемый псевдо-модификатор это не френды (плюсовые френды критикую в статье), а это коротко говоря:
publicс правилами.И следующая ваша цитата, мне кажется, продиктована этой путаницей с плюсами:
По примерам с nested классами и вообще о nested решениях:
Во первых попадаем под то проклятие — «эксбиционизм» плюсовых френдов (если используем именно inner класс как есть).
Не можем сделать один и тот же класс как nested сразу 2-х классов
Менее селективно.
Не всегда правильно загонять класс в nested (по моему опыту необходимости в элвис-модификаторе возникала в таких классах, которые ну совсем не годились чтобы из них делать nested пары).
Приведу такой сравнительный пример:
Скрытый текст
Насколько вас понял, под агрегатами (интерфейсы) имеете ввиду определять интерфейсы (или (абстрактные) классы) как nested с реализацией доступа с приватному функционалу внешнего, а потом где нужно наследоваться от этих интерфейсов.
Т.е. ровно то, что я описывал в разделе статьи «Через интерфейс» (очевидно, интерфейсов может быть сколько угодно). Ну а далее предложил и другой подход в виде псевдо-модификатора.
Спасибо!
Прежде всего отмечу, что, имхо, польза может быть особенно в проектах с большим, сложным внутреннем API, где важно строгое соблюдения контрактов/бизнес-логики.
Сборок может быть сколько надо, нет ограничений, главное чтобы аналайзер был ко всем ним подключен, или подключен хотя бы пакет с атрибутам, если в какой-то сборке функции аналайзера не нужны, но атрибуты используются (если все в одном сольюшене, то предлагался
Directory.Build.props).В разных они сборках или нет, в любом случае, они знают друг о друге (иначе как декларацию декларировать?). Знают и используют (уже имеем связь), если же не используют, то писал о варининге и TODO (или, наоборот, можно сказать, UNDO индикаторе, если оказался просчет в начальном проектировании).
Исходная сущность (класс
Me) внешне как раз не мутабельная (readonly), а"через интерфейс" предоставляется строго избирательная "проекция" с доступом к внешне скрытым или/и readonly мемберам.
Простите, про агрегацию, плохо вас понял. Имеете ввиду inner/nested классы (когда inner класс может получать доступ к закрытым мемберам outer класса)?
Про френды в C++ уже который раз пожалел, что вообще упомянул, они лишь начальная ассоциация, и, смотрю, каждый раз, «вызывают на себя огонь». Вот их можем отбросить, они лишь путают в понимании.
(а правило "три не" в плюсах, хорошее правило, если бы еще все его знали и использовали, это ведь только благое пожелание, а не запреты на уровне синтаксиса языка).
Помимо основного тела статьи, в «Приложении» сделал много примеров задач с возможным применением, обоснованием зачем. Думал достаточно (можно попробовать их решать другими методами, не спорю, и тогда уж сравнить что будет проще/лаконичнее...).
Про «торчащие нитки» (образное выражение), за которые могут дергать (т.е. использовать эти нитки-мемберы/классы: вызывать методы, сеттить свойства...) все (ну почти все с учетом более глобальных модификаторов) в том числе и те кому не желательно согласно контракту (это иллюстрировал в примерах).
internal и nested не дает той гибкости и селективности, как данный модификатор.
internal работает «по площадям».
nested не всегда возможен (а если нужен как nested сразу в нескольких классах? а если нужен «взаимный» nested?) и удобен, и он получает доступ сразу ко всем приватным мемберам outer класса (фактически как в плюсах в варианте не function friend), что не есть хорошо.
Про оценку ценности тут, конечно, пусть каждый сам приценяется, насколько ему интересен данный функционал (сугубо лично мне интересен).
Withkittens Спасибо за профессиональный пост!
Вы правы, есть разные решения, которые не умоляю. Да, и в Rust есть, что хотелось бы иметь и в C#.
Предлагаемый вариант, имхо, все же гибче, селективнее описанных вами подходов. В примерах в «Приложении» попытался показать применения. Возможно дело привычки (всегда кажется лучше и проще то к чему привык). Наверное пристрастен, только, имхо, просто поставить на мембере или классе/интерфейсе атрибут с вполне очевидным смыслом (Только Ты
<T>), не так уж напряженно. Вот вы, как понял, профи и в Rust, вот там, имхо, действительно сложные вещи (как минимум за себя скажу — ломал мозги когда изучал).Ну почему "прибиты гвоздями", вот новые появляются как тот же file модификатор. И, конечно, в CLR не лезу, кто же мне позволит? Ну назвал модификатором инструмент, который фактически выполняет функцию модификатора. Вы не согласны с названием, понял вас, уважаю ваше мнение (говорю, даже ни одного минуса не поставил вам в отличии от вас, после моих ответов). Смысл дальше спорить? (и не я его начинал, лишь вежливо отвечаю вам)
Потому как этот атрибут фактически и выполняет функцию модификатора доступа, конечно, нового модификатора не входящего в стандарт. Поэтому счел возможным назвать как модификатор.
У нас с вами дискуссии по названиям. Имхо, названия не столь важны как суть, предлагаю не продолжать их.
Увы, авторитетных доказательств что именно в C# тернарный оператор называется еще и Элвис оператором вы не привели. Уважаю ваше мнение и право называть что-либо как вы хотите, но пока тот же гугл не разделяет его. Даже не минусую ваши посты (в отличии от вас).
В статье же речь не об операторе, а о модификаторе, так что какая путаница?
Пожалуйста, приведите мне к-л авторитетное руководство по C#, где тернарный оператор называли бы элвис оператором. может плохо ищу:
https://www.google.com/search?q=Тернарный+оператор+и+Элвис+оператор+это+одно+и+тоже+в+C%23%3F&newwindow=1&client=opera&hs=Xco&sca_esv=2da575c93e33c7c8&sxsrf=ANbL-n7Jsk_eBKYYWIR76J2l42pvuAoU1Q%3A1773574077816&ei=vZe2aZrGMd39wPAP0tuvuQI&biw=912&bih=501&ved=0ahUKEwjamJCn5qGTAxXdPhAIHdLtKycQ4dUDCBE&uact=5&oq=Тернарный+оператор+и+Элвис+оператор+это+одно+и+тоже+в+C%23%3F
И, поверьте, не «лезу в бутылку», готов признавать свои ошибки (буду только благодарен если укажите на них, ставлю за них лайки, как тут ниже для chegeras и вам готов поставить), готов узнавать что-то новое. Просто пока не понимаю вас.
И опять замечу, что речь в статье о C#, не о Kotlin. В C# именно вот так
?:одной строкой вообще нет такого оператора.Это в Kotlin. В C# же (наш контекст) "?:" все же принято называть тернарным оператором (очень старый оператор еще до Элвис оператора):
https://www.google.com/search?client=opera&q=what+is+"%3F%3A"+operator+in+c%23%3F&sourceid=opera&ie=UTF-8&oe=UTF-8
и, как минимум, гугл не согласен называть его Элвис оператором в C#:
https://www.google.com/search?client=opera&q="%3F%3A"+operator+in+c%23+is+Elvis+operator%3F&sourceid=opera&ie=UTF-8&oe=UTF-8
Спасибо большое! Верно, в первой строчке опечатка, вы правы, конечно, должно быть:
me: 100; friend: -40Поправил.
На счет "?:" не встречал чтобы называли его "Elvis operator". Классический Элвис-олератор, как верно далее пишете, это "??" (также как и "?.", тоже относится к Элвис семейству операторов).
В каком-то смысле модификатор и защищает, только не от NullReferenceException, а от нарушения бизнес-логики/контракта.
Если бы не было «Elvis оператора», то наверное и не подумал так назвать модификатор, а так дорога уже проложена, считайте традиция, да и для «маркетинга», имхо, хорошее название (в кавычках, потому как какой маркетинг при MIT лицензии).
Как это принято, чтобы продемонстрировать концепт, для ясности приводится самый простой пример. И, конечно же, для таких примеров могут быть альтернативные решения, иногда более сложные решения иногда менее (да всегда есть альтернативные решения, более того, даже тот же C++ можно было не изобретать, ведь все задачи можно и на C решать — вопрос простоты/удобства). В реально жизни же такие демо-примеры — редкие исключения. И зачем, кстати, в стандарте C++ есть friend-ы? Вот, Stupid люди, ввели для несуществующих проблем.
Во-первых: а что если какой-либо или сразу оба класса уже имели базовые классы, так что для нового базового абстрактного класса уже не было бы места? (как знаем, в C# нет множественного наследования в отличии от плюсов)
И как уже писал в других комментах, этот инструмент может быть особенно полезен для программ со сложной логикой (там все места обычно заняты), а не «линейных», типа где почти лишь DTO-шки, ORM-отмаппенные классы из дата-сетов + шаблонные контроллеры созданные IDE для вас. Боюсь, что недоумение «зачем это нужно?» от некоторых здесь, и связано с тем, что люди привыкли заниматься такими шаблонными задачами (и это реальность почти всех разработчиков, сам большинство таких задач и решаю, но скоро AI вытеснит программистов из шаблонных задач). Это инструмент для сложных задач, для «ювелиров» настраивающих сложный часовой механизм vs «слесарей» занимающихся рубкой метала где инструменты это молоток и зубило.
Во-вторых: пусть не «во-первых» (т.е. место под базовые классы все же есть), и если правильно вас понял, предлагаете:
Увы, компилятор не согласен (2 ошибки компиляции).
Если же поле определить как:
То оно уже будет доступно и всем другим классам в проекте, а не только наследникам
Base.Как вариант решения этой задачи без атрибутов (решение более сложное + с недостатками оговоренными в статье) — см. пример с
Me.IFriendинтерфейсом в статье.Вы действительно считаете, что добавить ВСЕГО ОДНУ СТРОЧКУ с атрибутом и означает все что вы тут написали? Одна строчка:
В еще более лаконичном варианте, так:
А на счет зависимостей (их иллюзорности) можете почитать мой ответ в другом комменте — прокрутить до места, где отвечаю коллеге про объектную модель (и связность):
https://habr.com/ru/articles/961264/comments/#comment_29067094
И что, разве через определения базовых классов, наследования для каждого, создания всей этой иерархии зависимостей... разве код уже не раздуваем, не делаем сложно читаемым (vs ясного и лаконичного
OnlyYouатрибута одной строкой)?Если внимательно почитаете статью, то найдете, что как раз это критикую в C++ friend-ах. Хотя friend-ы вполне себе входят в стандарт C++.
Как уже отмечал, имхо, при использовании любого инструмента нужно пользоваться головой, ибо всегда, даже самый хороший инструмент можно извратить, довести до абсурда в его применении. Это касается и инструментария в статье. По моему опыту, даже в сложных задачах, применение elvis-модификатора в среднем требуется к 1 методу на 100 классов, а вовсе не безбашено лепить на каждый метод, каждого класса.
Важно: Как писал и в статье и во многих комментах, предложенный подход уже не совсем аналог плюсовых friend-ов. Другой инструмент, избавленный от важных недостатках плюсовых friend-ов. Можно сказать, это вообще не friend-ы. Они были лишь одной из мыслей-истоков, аналогией от которой оттолкнулся.
Правильнее говорить о новом, более селективном модификаторе доступа (elvis-модификаторе). Модификатор не открывает приватные члены (не нарушает private контракт), а делает селективным доступ к публичным.
Например, вот где (помимо статьи) более подробно говорю:
https://habr.com/ru/articles/961264/comments/#comment_29068288
А private контракт ломает разве что рефлексия.
Аналайзеры же (тем более без фиксов как здесь) в принципе ничего не ломают, а лишь выдают ошибки/предупреждения при компиляции. Более того, если программист сам явно не добавит elvis-модификатор, то аналайзер никак себя и не проявит, как если бы его и не добавляли в проект.
Чтобы не путали с friend-ми даже возникло желание переименовать проект в ElvisAnalyzer (+ маркетинг хороший, хотя все бесплатно, все для вас дорогие, хоть бы кто спасибо сказал, кроме одного, только ругают и минусуют).
---------------------------
Спасибо вам большое, что хоть задали технические вопросы, а то, к сожалению, тут скорее заняты художественным аспектом (некоторыми аспектами «одежки» статьи, а не сутью) и моей личностью, даже не приводя конкретные аргументы.
Впрочем, и вы без наездов на мою Stupid личность не обошлись :) (хотя, реально, бывает туплю) Но уже и такому рад — «на безрыбье и рак рыба», коль без наездов никак (если что, просто поговорка, а не обзываю вас «раком», уважаемый коллега).
Так давайте и обсуждать техническую часть, а не художественную. Рассчитывал, что именно-именно так и будет. Только и только «за» и руками и ногами.
Вместо этого в основном переход на личности (причем «заметьте, не я это предложил» — такую тему, или мне стоит быть польщенным к такому вниманию к моей личности?).
Да, есть у меня свои индивидуальные особенности. И народ за них зацепился (а мне вот не нравиться как мой сосед одевается, но тем не менее хорошо общаюсь с ним, никогда не поднимая тему его одежды). Их можно либо попытаться понять (и даже вдруг тут открыть для себя что-то новое, моим друзьям/знакомым — нравится), либо абстрагироваться от них. Тем более в технической части статьи этого немного. Ну либо, на самый худой конец, вот так как сейчас... хорошее тут слово было в постах, а вот, нашлось — «наезжать» (можно позаимствую?). Тоже вариант и ваше право.
Т.е. что же это получается? По факту многие люди здесь показали, что им гораздо важнее художественная, а не техническая часть? Одежка, а не внутренность?
Знал бы что будет такая неожиданная реакция — конечно по другому бы написал, для вас дорогие коллеги, сломал бы себя (пусть и поется в песне «Но не смотри, не смотри ты по сторонам, Оставайся такой, как есть, Оставайся сама собой...»).
Это первая (и похоже последняя) моя статья, о чем писал в самом начале и просил «Пожалуйста, позаботьтесь обо мне».
Что же, так вот она какая забота («вот он какой северный олень»), Ваше право.
P.S. И может быть если бы вы чуть лучше разбирались в людях (простите, если ошибаюсь) то знали бы что часто люди шутят не от хорошей жизни. Жизнь боль и не только своя, но и близких. А юмор он помогает держаться. Если у вас все прекрасно, то реально рад за вас (всегда молюсь чтобы Господь и дальше хранил счастливого человека которого вижу).
Ну, да, извините, что уделяю вам свое время, внимательно читаю ваши посты и стараюсь максимально полно ответить вам. Пожалуйста, не будьте к себе строги, уверяю, «ведь вы этого достойны!». Так что какие наезды? Извинения и благодарности. Хотите знать что такое наезды? Тут далеко ходить не надо — есть, есть тут характерные посты, можете перечитать на досуге, если забыли.
«ИМХО», конечно было в одном вашем хорошем посте, на который, имхо, хорошо ответил.
Только отвечали то вы мне, а потом я вам на содержание другого поста, гораздо ниже. Потеряли контекст? Тот ваш пост, который уже, как бы это помягче сказать чтобы вас не обидеть... Ай, не буду говорить, не хочу вас обижать, дорогой коллега.
А что с оправданиями не так? Не имею право отвечать? А кто тогда защит меня бедного детсадовца от взрослых и таких невообразимо умных дядей?
Даже вот очень известная фраза гласит: «...Вы имеете право на адвоката. Если вы не можете позволить себе адвоката, он будет назначен вам бесплатно».
Тогда требую бесплатного адвоката! Пусть он меня оправдывает, а я буду «хранить молчание».
полная цитата вашего поста на который ответил:
Вам дали пересоленную еду. Вы говорите: невозможно есть, она очень-очень солёная, соль даже скрипит на зубах. Но вам отвечают: вы просто глупый, ленивый, поверхностный, не разбираетесь в кулинарии, и вообще вот вам две, даже три часовых лекций на тему, почему вы должны поверить, что это шедевр.
Научитесь, наконец, принимать критику, как взрослый человек. Ваши кирпичи текста в комментариях не добавляют ясности, а только ещё больше усугубляют. Вы не обязаны с каждым соглашаться, но обвинять окружающих в лени, тупости, посредственности только потому что не оценили ваших художеств — хамство, не иначе.
Где "ИМХО" то? Или не только у меня проблемы?
И вам что завидно, что на вежливый положительный ответ — вежливо положительно ответил? (если так, то, пожалуйста, не надо, читал, что согласно статистики, зависть — основная причина депрессий в США, поберегите себя).
Впрочем и вам и всем вежливо отвечаю (так что, еще раз, пожалуйста, не приписываете мне своих мыслей). Более того, даже вам вот ниже постом немного отлизаблюдил (в вашей терминологии).
Также благодарю вас, что отслеживаете и собираете библиографию моих постов (вот еще раз вам отлизаблюдил). Не хотите стать моим летописцем?
Коллега, а вы не находите, что вы мне тут столько всего наговорили, столько своих непрошенных оценок навешали, что тут можно долго разбирать всякие ваши issues, давая встречные оценки (может даже «букетик» issues? как это принято мягко называть в английском, ведь у них всегда «no problem», это только у меня по вашим словам серъзные problems). Но нет, так никак не могу, ведь как и все воспитанные люди, понимаю, что без запроса от собеседника самому давать ему оценку крайне не этично. В свою очередь, извините, если где-то невольно что-то проскочило.
И вот что мне странно: у меня есть сейчас время (ведь ~ «ленивые часов не наблюдают»), и я с удовольствием общаюсь с вами (получаю «роскошь человеческого общения»). Вдруг меня (глупого конечно), умные и взрослые дяди научат не только плохому, но и чему-то хорошему (и да, есть уже результаты/выводы, спасибо всем!). А вам вот все не нравится, но вы упорно продолжаете общаться (на кактусах тренировались?). Все-таки какие мы все разные и как же это интересно!
Некоторые образы понравились, реально хороши (не ai случайно? просто похоже). Единственное, уж очень, очень, имхо, гипертрофировали в попытке сарказма.
Чашка кофе с ложной сахара и чашка сахара с ложной кофе - чувствует разницу?
Но не настаиваю, не осуждаю «вы художник — вы так видите».
У меня свое мнение, у вас свое. Или считаете это ненормальным?
Спасибо за ваше мнение, оно очень ценно для меня!
И после этого вы говорите, что не воспринимаю критику? :)
Уважаемый, очень взрослый человек, стесняюсь спросить: а на критику можно отвечать, просить аргументировать? Или только в духе «ему ссут в глаза — а он божья росса». Ибо как можете заметить она тут очень лаконична, без аргументации, порой просто фразой-эмоцией, и если бы она была применена к вам, то возможно (возможно, не настаиваю конечно), то вы бы ее, наверное (наверное) как раз и назвали детским садом.
Как же мощно вы меня припечатали, просто намотали на гусеницы: «вам отвечают: вы просто глупый, ленивый, поверхностный, не разбираетесь в кулинарии».
Позвольте, ну не совсем все же верно (хотя иногда и бывает что туплю) и это не мое мнение, «у меня и справка есть» (и совсем не об окончании «кулинарного техникума» и совсем даже не на двойки, а с точность наоборот).
«Ленивый»? (хм, труд проделал огромный — реально, + тут, стараюсь, каждому очень-очень развернуто отвечаю, задаю вопросы...). Признали щедевром? Где на такое надеялся? Пожалуйста, прошу, не надо за меня выдумывать, ведь это справедливо считается очень не этичным. В таких случаях просто спросите меня, если хотите знать что реально думаю (а не что вы думаете, что я думаю, что я думаю).
Да и отвечают не все как вы, есть тут совершенно другие мнения.
Замете, остаюсь с вам в рамках вежливого общения, несмотря на откровенное хамство.
А теперь можете ставить свой очередной минус (ну если захотите, конечно, ведь не вежливо указывать другим что им делать, так что, конечно, не настаиваю).
Спасибо Огромное! Ваш комментарий особенно ценен на фоне превалирующего непонимания.
Почитав иные комменты, считаю, что люди просто не поняли материал статьи.
А некоторые, похоже, даже не потрудились дочитать (но осуждают). Особенно первые 2 мгновенных минуса, сразу, в ту же минуту, после публикации. Возможно это были северо-корейцы, которые прочитали лишь первый абзац со ссылкой на цикл о Южной Кореи (но ведь тоже не потрудились прочитать цикл, ибо там совсем не воспеваются порядки южан).
Написал, имхо, полезный инструмент, выложил в открытый доступ, берите пользуйтесь на здоровье, если кому понадобится.
Статью с любовью запилил, стараясь ее сделать не скучной, чтобы люди не засыпали на бубнеже о технических деталях, разбавил шутками юмора.
Хотя это больше про небольшие вводную часть и заключение, в которых традиционно вполне допускаются лирические ноты. Основная же часть, имхо, должным образом (как многие требуют) скучная.
Даже не ожидал, что это будет такая огромная работа (причем все «безвозмездно, то есть даром» от чистого сердца).
И, думаю, конечно, тут каждому будет по человечески обидно.
Сижу-гадаю: «что же вам, собаки, еще надо-то?!»
Ладно, извиняюсь (пред теми кто отнес на свой счет, не понял юмора, цитаты) — собаки зачеркиваю, это я сгоряча, на эмоциях. Хотя «собака — друг человека», так что вполне в рамках тематики статьи :)
Некоторые вообще за рамки элементарной этики выходят (поплачусь в жилетку):
https://habr.com/ru/articles/961264/comments/#comment_29059274
Настолько в когнитивном диссонансе от «ожидание и реальность», что, думаю, уже никогда здесь больше не решусь написать что-либо еще (хотя идей достаточно).
Так что, еще раз, моя вам искренняя благодарность за понимание, умный, образованный, с хорошим чувством юмора человек.
Это поясняемая цитатами и пословицами — доказательная логика: почему число 100, а не любое другое как могли бы недоумевать, и почему надо делится с другом, и почему именно «на лапопам».
Чтобы не было вопросов что тут за цифры и действия такие взятые с потолка или с бодуна. Так сказать описание предметной области, которая будет моделироваться программой. Ну и постарался сделать это не скучно. А без цитат, ссылок-отсылок в серьезных изданиях так вообще не примут статью :)
По идее такие описания должны восприниматься влет, легко и приятно, как хорошо знакомые и ярко-выпуклые образы, легкими мазками рисуя в воображении читателя живую «картину маслом» (эх, вот опять не удержался от цитаты). Если же спрашиваете: какие ключи, рубли, квартиры, тумбочки. То значит можно сделать вывод, что не находитесь в классическом русском контексте пословиц, мемов, литературной и кино-классики. Вот с этим ожиданием от читателя возможно и промахнулся. Переоценил народ в этом плане.
Хотя это больше про небольшие вводную часть и заключение (как уже говорил), в которых традиционно вполне допускаются лирические ноты. Основная же часть должным образом (как многие требуют) скучная. Ну а редкие вкрапления юмора... так в чем проблема просто пропустить их, если этот юмор не понятен? (ну или у меня он такой не смешной или слишком требовательный к читателю, эх, а ведь старался веселить, т.е. вызывать положительные эмоции).
Честно говоря даже верится что вот это было непреодолимое препятствие, имхо, даже одних примеров кода, которыми постарался обильно снабдить статью, достаточно. Больше похоже на то, что некоторые просто не поняли (поленились) материал статьи, об этом говорят и некоторые из их постов (развернуто отвечал на их все).
По моему опыту не так уж и редко для задач со сложной логикой. Если писать к-л типовой проект, бэкэнд рядового интернет магазина какой-нибудь, то там, да, все более-менее линейно. Другое дело, когда задача со сложной логикой.
Как говорил в статье, следуя ФП дао-пути, всегда так стараюсь выстроить систему классов приложения, чтобы классы в идеальном случаем имели только readonly публичные свойства. Увы, как раз для «нелинейных» задач это не всегда просто удается (а если делать не просто, то обычно уж слишком не просто, непроизводительно, не стоит свеч). Некоторые классы оказываются семантически связанными. Какие-нибудь пары например, при работе одного класса-обработчика необходимо скорректировать некоторое свойство в другом. Но в проекте еще очень много классов, которые видят и читают это свойство, этот класс. Поэтому только ради одного кейса открывать его для всех (public { get; set; }) совсем не хочется.
Особенно в больших, командных проектах иногда видел, что чуть ли не все свойства (надо - не надо) имеют публичные get-set. Вот смотришь на миллион таких классов (особенно на чужие, да и на свои сколько-то времени спустя) и чешешь репу — да где же только в этом огромном коде с миллионом классов и миллионом мемберов в них (ладно, не буду вас цитировать — ограничимся хотя бы 1000) не треплют эти свойства? Напоминает пресловутый антипаттерн глобального состояния, только, имхо, хуже, ибо это состояние, размазано по массе классов и попробуй разберись, как оно меняться, если каждый может изменять каждого. А вот если все неизменяемое, то все куда-куда упрощается, намного проще понять логику. И описываемые в статье инструменты позволяют приблизится к этому идеалу.
У меня в проектах практически все классы неизменяемые. Имеются только очень выборочные исключения для некоторых мемберов, которые открыты, но не тысячам других классов, так что они были бы способны их «матросить», а только одному/двум (intellisense же при большом числе классов с их массой мемберов в каждом тут слабо помогает). Смотришь на них и все прозрачно, видишь явную логическую связь — не тысячи возможных нитей-связей, за которые могут все дергать, а одна/две явно прописанные.
ну да, про этот как раз в первой половине статьи и писал (см. Me.IFriend)
Про инкапсуляцию так бы сказал (собственно писал про это): не нарушает ее, в скорее дополняет еще одним инструментом. Вводит еще один, можно сказать, модификатор доступа, более селективный модификатор (elvis модификатор). И лично мне нравятся такие тонкие инструменты — как инструменты ювелира vs инструменты слесаря, ими уже можно всякую тонкую, так сказать, «часовую механику» налаживать, а не только рубить метал зубилом с молотком. Яйца фаберже vs рессоры от трактора беларусь :)
Еще дополнительные аргументы (там где про объектную модель и связность) привожу в ответе на другой пост:
см. https://habr.com/ru/articles/961264/#comment_29067094