Войти
Инди-ЮнитиФорум

Мастер класс по хорошему коду в юнити (15 стр)

Advanced: Тема повышенной сложности или важная.

Страницы: 110 11 12 13 14 15
#210
20:01, 28 окт. 2020

cNoNim
> является примером подключения того ECS к Unity
а т.е. системы к ECS не относятся ... они мол только для подключения к юнити ... ну, норм такая себе философия :)

а что там остается?

#211
(Правка: 3:40) 3:17, 19 дек. 2020

Заметка про инкапсуляцию

В очередной раз, столкнулся с кашей в голове, в этот раз на тему с инкапсуляцией. Состоялся такой разговор:

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

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

A. делая public bool isDead вы нарушаете принципы инкапсуляции. И все ваше свойство можно заменить простым и понятным методом Dead()

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

public bool IsDead;

объявят свойство

public bool IsDead {get; set;}

а не которые пойдут еще дальше, и начнут возмущаться, что в set есть некая логика (в данном случае, синхронизация с параметрами аниматора)

    private bool isDead = false;
    public bool IsDead
    {
        get
        {
            return isDead;
        }
        set
        {
            if (isDead != value)
            {
                animator.SetBool("IsDead", isDead);
                isDead = value;
            }
        }
    }

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

1. "преимущество, косвенного доступа к переменной состоит в том, что он позволяет переопределить
.. получение [и запись] информации"
2. "преимущество прямого доступа к переменной заключается в легкости чтения кода"
3. "я предпочитаю сначала применять непосредственный доступ к переменной, пока это не становится препятствием. При возникновении неудобств я перехожу на косвенный доступ. А рефакторинг предоставляет свободу изменить свое решение"

Вот по сути и все. Нет ни какого абсолюта "делая public bool isDead вы нарушаете принципы инкапсуляции", нет ни какой необходимости каждое поле инкапсулировать через свойство. Сама фраза "нарушаете принципы инкапсуляции" - уже странная, нельзя нарушить принципы инкапсуляции, можно или применить инкапсуляцию поля свойством, или нет. И по умолчанию (вначале) это не нужно. И только тогда, когда возникает необходимость, что-то делать ВСЕГДА при получении или присваивании/изменении значения - имеет смысл использовать свойства.

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

Итого, когда вы видите кучу

public bool IsDead {get; set;}

это уже "код с душком".

В других языках (например, Яве) до сих пор нет гетеров/сеттеров, вот только тогда это заменяют методами. Ну или если логика в гетере/сетере становится на столько сложной, что она разрастается это стоит выделить в метод, но на общих основаниях, вызывая их все равно из get/set.

У человека же выше - все поставлено с ног на голову.
1. Вначале человек говорит, что не стоит использовать логику в get/set мол для лучшей читаемости кода
2. Потом говорит, что использование полей это нарушение инкапсуляции
3. И наконец, тянет эту логику в какие то частные методы

И загоняет себя в абсурд, и я даже уверен, что и сюда зайдут такие же ... :)

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

не поверил бы, если сам с таким не встретился бы ...

#212
12:43, 19 дек. 2020

Поля (Руководство по программированию в C#)

"Как правило, следует использовать поля только для переменных, являющихся закрытыми или защищенными. Данные, которые класс представляет клиентскому коду, должны предоставляться через методы, свойства и индексаторы. Используя эти конструкции для косвенного доступа к внутренним полям, можно предотвратить использование недопустимых входных значений."(c)

без понимания терминов инкапсуляции, интерфейса и контракта вероятно сложно это осилить :) - но ты дерзай и все получится
#213
(Правка: 15:16) 14:55, 19 дек. 2020

patsanchik3
ну, да, вот так вы и учитесь через интернет :)

patsanchik3
> должны предоставляться через
а почему должны? это понять видимо не суждено :)

а это в сл. строчке

patsanchik3
> можно предотвратить использование недопустимых входных значений
а это нужно уж конечно же всегда :) ...
вот даже интересно, а это происходит в

public bool IsDead {get; set;}

упс ... сел в лужу, студент? может вначале научишься читать, что написано?

#214
15:41, 19 дек. 2020

в кой-то веке tac разбавил свою графоманию невежеством менее чем на 50%.

> public bool IsDead {get; set;}
не имею возможности залезть в голову всем, кто так пишет, но вижу две более-менее уважительные причины так делать:

1. бинарная совместимость библиотек.
допустим, мы в своем приложении (игре) используем либы A и B. Либа A зависит от либы B, обращаясь к свойству SomeValue1 (которое объявлено как auto-property) класса Class1 из либы B. В какой-то момент времени, автор либы B испытал потребность в добавлении некой логики к каждому доступу к свойству SomeValue1 и превращает auto-property в обычные property с кодом в геттерах и сеттерах. После этого автор либы A ничего не делает, а пользователи либ A и B просто обновляют либу B.

Теперь включим машину времени и заставим автора либы B изначально объявить SomeValue1 не как auto-property, а как обычный field. Теперь, чтобы переопределить доступ к этой переменной, придется превратить SomeValue1 из поля в свойство, а для того чтобы это изменение дошло до игры, автору либы А придется перекомпилировать либу и выпускаь новую версию, а разработчику игры - обновлять и ее тоже.

2. совместимость модели с библиотеками.
допустим, мне нужна либа для работы с JSON. из всех либ для C# мне в свое время подошла та, которая требовала чтобы все поля у моих DTOшек были именно properties, а не fields. Даже если предположить что авторы либы не очень умны что ввели такое ограничение, то либа в целом весьма стабильная, функциональная и хорошо расширяемая. пойти на принцип и отказаться в пользу более слабой либы но с поддержкой полей? выбора за вами, конечно.

(2...N]
Вот как раз пока пытался найти ту самую либу (не нашел - лень), гугол меня навел на офф руководство как работать с JSON стандартными дотнетовскими средствами. И вы не поверите, неокрепшие умы проникли в MS и пишут документацию:

public class WeatherForecast
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
}
В общем, раз уж авторы платформы рекомендуют использовать auto-properties, то можно и потратить чуть брэйнпавера чтобы подумать над причинами юзать auto-properties, и внезапно их найти, прокачав свой нюхометр.


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

#215
(Правка: 16:45) 16:14, 19 дек. 2020

kkolyan
> бинарная совместимость библиотек.
Серьезно, они независимые библиотеки пишут для разработчиков игр? Не смешите мои тапки ...

при этом этот вопрос связан с особенностями компиляциями, в одном случае от ищет "Field not found", в другом "Method get_ not found" ...

сам же код не меняется вообще, т.е. разработчику B, не нужно менять код, а только скомпилировать. В то время как разработчики Unity часто делают не совместимые версии, например до сих пор встречаю старые версии, где приходится заменять на GetComponent<Render>, а не пользоваться прямо полем render ... это я вам скажу чистоплюйство, но оно не стоит такой цены.

> а разработчику игры - обновлять и ее тоже
нет, это уже не нужно ...

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

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

и опять в 90% случаях засрав код, на всякий случай, авто-свойствами ... которые так и останутся, и никогда не изменятся на свойства с логикой. Тем более, если вы не любите логику в свойствах - так почему же вы не используете поля. Ваша же "не любовь" должна гарантировать отсутствие необходимости в свойствах вообще. Вы или штаны оденьте, или крест снимите ...

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

#216
16:35, 19 дек. 2020

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

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

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

как обычно истина где то посередине

#217
(Правка: 16:53) 16:41, 19 дек. 2020

patsanchik3
вы не выдавайте свое мышление гавнокодера, за мышление программиста

после такого мышления как у вас появляются байки "Как программисты хлеб пекли", где закономерный вывод ООП - зло ... в вашем исполнении приходится согласится ... но с реальным ООП это не имеет ни какой связи

И таки да, программировать надо здесь и сейчас, а не выдумывать себе не нужные задачи, и потом тянуть говнище через всю разработку ... код должен сиять от чистоты, а не быть наполнен "сгнившей соломой", которая то и в теории на 90% никому не нужна, а в реальности и на все 100.

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

#218
17:23, 19 дек. 2020

tac
"По сути весь этот топик посвящён тому, какие есть недоразумения в мозгах, которые наполняют разработку "сгнившей соломой", а не рабочим кодом."

топик носит гордое название "Мастер класс по хорошему коду"
но до сих пор в топике так и не было примеров кода от ТС!
и пока подобного не произойдет и автор сего творения как попытки самоутвердится в своих заблуждениях не предоставит на общее обозрение примеры хорошего кода в виде хотя бы небольшого проекта на публичном репозитории - данный топик больше тянет на флейм а автор на неадеквата :)

покажи сеточку примеры хорошего кода

#219
(Правка: 21:32) 21:22, 19 дек. 2020

patsanchik3
> в топике так и не было примеров кода от ТС!
вранье, я тут много кода своего показывал, перечитайте ... причем такого, который стоит использовать вместо ваших фантазий о ESC, реактивности, сериализации, и прочего гавно фреймфорков ...

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

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

#220
(Правка: 21:29) 21:28, 19 дек. 2020

patsanchik3
> хотя бы небольшого проекта на публичном репозитории
+1. впрочем я смотрел по-диагонали код Maze и мне не особо будет интересно смотреть то, что автор опубликует. но это хотя бы будет не просто брюзжанием на тему "все тупые, я умный".

#221
21:31, 19 дек. 2020

kkolyan
> впрочем я смотрел по-диагонали код Maze
вы его не могли видеть :) а то, что вы реверснули - это не мой код, а в известной степени машинная компиляция

Страницы: 110 11 12 13 14 15
Инди-ЮнитиФорум