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

По ссылке "Когда нужно MVC, как сделать Binding визуальных контроллов с методом (UNITY, C#, Разработка игр)" вы можете послушать меня, а кто хочет почитать прошу подкат.

Первое условие: у вас в игре хотя бы две сцены: главное меню и собственно игра.

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

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

Где здесь проблемка? По умолчанию, при смене сцены, все что там было удаляется. Но есть возможность, использовать метод юнити DontDestroyOnLoad (о нем можно найти в документации или на моем же канале), но я думаю все кто читает более сложные темы об этом знают и мы идем дальше.

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

MVC как таковой, выполненный без биндинга, на уровне поддержки фреймворка, совершенно устарел, может быть лишь теорией. Если вы попробуете реализовать MVC согласно Фаулеру (у него есть пример для языка Java), то на это без слез не взглянешь. Он приводил его в качестве теоретического примера, а не как руководство к действию. Фреймворки с биндингом из известных - это WPF и ASP.NET (о качестве их разговор отдельный, но он есть).

Но так ли сложно реализовать этот биндинг самому? А ведь он нужен в Юнити. Оказывается, это сравнительно просто. Проще, чем реализовывать в ручную MVC для 3 классов.

Для этого мы возьмем UnityEvent

[System.Serializable]
public class BindingEvent
{
	public string Name;
	public UnityEvent Event;
}

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

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

[System.Serializable]
public class BindingBehavior
{ 
	public string Name;
	public Button Button;
}

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

Теперь нам нужно создать класс ответственный за биндинг:

public class BindingUI : MonoBehaviour
{
	// Список визуальных элементов
	public List<BindingBehavior> BindingBehavior;
	// Список методов
  public List<BindingEvent> BindingEvent;
	// Партнер для связывания
	private BindingUI Related;

	// Найти партнера в зависимости от сцены
	public BindingUI GetRelated()
	{
		BindingUI ret = null;
    ...
		return ret;
	}
}

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

И для фреймворка останется реализовать собственно лишь связывание:

	private void Bind()
	{
    // Для каждого визуального контрола поищем метод, с которым его надо связать
		for (int i = 0; i < BindingBehavior.Count; i++)
		{
			BindingEvent eventContainer = null;
      if (Related != null)
      {
        if (IsDoneBinding(BindingBehavior[i].Name) == false)
        {
          eventContainer = Related.GetBindingEvent(BindingBehavior[i].Name);
          AddDoneBinding(BindingBehavior[i].Name);
        }
      }
			if (eventContainer != null)
			{
				BindEvent(BindingBehavior[i], eventContainer);
			}
		}
		if (Related != null)
		{
      // Для каждого метода, поищем визуальный контрол, который не знает как себя вести
			for (int i = 0; i < BindingEvent.Count; i++)
			{
				if (IsDoneBinding(BindingEvent[i].Name) == false)
				{
					BindingBehavior behaviorContainer;
					behaviorContainer = Related.GetBindingBehavior(BindingEvent[i].Name);
					if (behaviorContainer != null)
					{
						BindEvent(behaviorContainer, BindingEvent[i]);
						AddDoneBinding(BindingEvent[i].Name);
					}
				}
			}
		}
	}

	// собственно связывание
	private void BindEvent(BindingBehavior argBehavior, BindingEvent argEvent)
	{
		if (argBehavior.Button != null && argEvent.Event != null)
		{
			UnityEvent locEvent = argEvent.Event;
			argBehavior.Button.onClick.AddListener(argEvent.Event.Invoke);
		}
	}

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

Вот и все сложности. Надеюсь, хоть на день упростил вам программирование :)

Комментарии (13)


  1. dive155
    11.06.2022 12:05
    +6

    Оно всё конечно здорово, но в вашем примере качество кода сперва стоит улучшить, исправив readability косяки.

    Но сперва по существу вопроса: MVC практически не заменимая штука, когда над игрой работает дев в паре с тех. артистом. В таком случае как раз прогер делает большую часть логики в MC, пока тех. артист пилит всякие красивости для V. Если бы они работали в одном общем классе то это была бы во-первых боль при работе с системой контроля версий, а во-вторых код связанный с визуалом имеет свойство быть очень объемным и игровая логика может в нём просто потонуть, ухудшая читабельность.

    А теперь по читабельности примера. Вы уж простите но меня триггерит, когда в статье про паттерны и архитектуру сам код-пример нуждается в рефакторинге х)

    1) Проверка на false

    if (IsDoneBinding(BindingBehavior[i].Name) == false)
    Не надо так ???? Давайте использовать цивилизованный

    if (!IsDoneBinding(BindingBehavior[i].Name))

    2) Кеширование локальной переменной
    Нет нужды несколько раз вызывать BindingBehavior[i].Name в пределах одной итерации цикла. Во-первых это создает усложняющую чтение визуальную нагрузку, а во-вторых чуть-чуть добавляет работы процессору (хоть извлечение по индексу это и очень быстрая операция). Лучше один раз закешировать это в локальную переменную и пользоваться ей.

    var behaviorName = BindingBehavior[i].Name;

    3) Разбиение методов на логические части пустыми строками

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

    4) Диагональный ветвистый код

    Если у нас в коде появляется if, вложенный в if, вложенный в цикл, вложенный в if, то что-то явно пошло не так. Человеческому мозгу проще воспринимать линейный код чем пытаться отследить все ветви кучи ifов. Как rule of a thumb, я стараюсь держать индентацию в пределах 2х, максимум 3х табов. В этом хорошо помогает на мой взгляд один из самых недооцененных readability паттернов early return, суть которого заключается в том что мы вместо расписывания всех возможных ветвей кода просто выходим из метода раньше времени (или уходим на следующую итерацию цикла).

    Для наглядности всего перечисленного вот исправленный метод Bind():

    https://pastebin.com/mSSMm2eL

    PS А еще у меня подозрение что этот метод вообще ничего особо делать не должен, если у нас Related == null (но я не знаю что у вас происходит в IsDoneBinding и AddDoneBinding, которые вы почему-то в пример не включили. Но если в них переменной Related значения отличные от null не присваиваются, тогда код можно упростить еще сильнее: https://pastebin.com/79qpcvPX )


    1. tac Автор
      11.06.2022 14:43

      Вы не правы по всем пунктам, я пояснять не буду. Но прежде, чем придираться к мелочам, начните правильно использовать MVC. Захотите от меня ответов - спросите уважительнее.

      тех. артист пилит всякие красивости для V

      код связанный с визуалом имеет свойство быть очень объемным и игровая логика может в нём просто потонуть

      Серьезно? артист пишет такой код? кого вы пытаетесь насмешить, и тем самым оправдать применение MVC ради самого применения?

      Может для декомпозиции кода, нужно не MVC использовать? И не только коде стайл использовать популярный, который просто кричит глупостями?

      Если у нас в коде появляется if, вложенный в if, вложенный в цикл, вложенный в if, то что-то явно пошло не так.

      Так как это настолько часто возникающая несуразица, я лишь спрошу где источник этого несерьезного утверждения? Вы думаете, заменив это на return вы сделали лучше? Тогда я посоветую вам использовать goto они позволяют убрать больше if :)

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


      1. sedyh
        11.06.2022 20:02
        +1

        Так как это настолько часто возникающая несуразица, я лишь спрошу где источник этого несерьезного утверждения? Вы думаете, заменив это на return вы сделали лучше?

        Настоятельно рекомендую открыть линтер.


        1. tac Автор
          11.06.2022 20:55

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

          P.S. А о качестве кода я лучше знаю, чем любая автоматизированная шняга ... скорее будут вопросы к её разработчикам.


      1. dive155
        11.06.2022 22:33
        +4

        Мои источники - 5 лет коммерческого опыта, из которых полтора года в Британском юникорне, в котором меня на ревью за такое качество кода как минимум попросили бы объясниться и отправили переписывать)


        Вы говорите про неуважение, но я в комментарии ни слова не сказал про вас. Неумение отличать критику кода от критики написавшего его человека это распространённая проблема, которая может привести к трудностям в командной работе. Решается транспарентностью в коллективе и прокачкой emotional intelligence.

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

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


        1. tac Автор
          11.06.2022 23:54

          Мои источники - 5 лет коммерческого опыта

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

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

          Отвечать вам надо, почему вы думаете, что все что вы написали вообще имеет смысл обсуждать? Зачем мне с вами обсуждать ваши глупости? Ну выучились вы где-то не так ... мне что до этого?

          Вам объяснить и так надо ...

          1. Почему вы позволили себе использовать переменную var в строготипизированном языке?

          2. Почему вы бесполезно ввели лишнею переменную behaviorName

          3. if (IsDoneBinding(BindingBehavior[i].Name) == false) - нет именно так и надо, почему вы предпочитаете "усложняющую чтение визуальную нагрузку" аналог ?

          4. Почему вы позволяете себе return в методе ничего не возвращающем, почему не используете goto?

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

          И нет, вы позволили себе - учить меня тому, чего я не просил! Учить тому, что как минимум спорная практика, да спорная! Кто вам скажет, если не такие как я ... больше читайте теории, в голове будет еще больше каши. Вы мне еще расскажите как скобки ставить ...

          И все это при том, что статья совершенно о другом. Вы утрудили себя хотя бы прочитать предыдущую статью, разобрать в этой и понять когда нужен MVC, и как его учат использовать? А ведь учили там тоже мол учитель в МФТИ с опытом коммерческой разработки ...

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

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


          1. dive155
            12.06.2022 21:47
            +3

            Давайте начнем с того что написано по-существу:

            Почему вы позволили себе использовать переменную var в строготипизированном языке?

            Ничего страшного, строгая типизация никуда не денется, нужный тип выставится компилятором на этапе сборки. Вы даже можете получить все те же complie time errors как если бы тип переменной был объявлен явно (Источник https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/var)
            С другой стороны, использование var избавит нас от необходимости изменять объявление переменной behaviorName если тип BindingBehavior[i].Name изменится на другой. Бонусом мы также получаем более аккуратный код при объявлении нескольких переменных подряд, пример:
            // Зачем два раза писать имя класса? Визуальный мусор

            // Индентация до имени везде разная - создает friction при чтении кода

            Foo foo = new Foo();

            List<Foo> fooList = new List<Foo>();

            bool isFooSpawned = foo.IsSpawned;

            Против:

            var foo = new Foo();

            var fooList = new List<Foo>();

            var isFooSpawned = foo.IsSpawned;

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

            Почему вы бесполезно ввели лишнею переменную behaviorName

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

            if (IsDoneBinding(BindingBehavior[i].Name) == false) - нет именно так и надо, почему вы предпочитаете "усложняющую чтение визуальную нагрузку" аналог ?

            Это наверное самое субъективное из всего списка. Вариант с явным сравнением с false сильнее визуально нагружает, на мой взгляд. Я допускаю что вы можете думать иначе и это ваше право, но я не понимаю как
            if (condition1 == true && condition2 == false || condition3 == true)

            может быть более читабельно чем

            if (condition1 && !condition2 || condition3)

            Почему вы позволяете себе return в методе ничего не возвращающем, почему не используете goto?

            Я не использую goto потому что он избыточен для данной ситуации (да и вообще юзать goto это так себе практика), более того, зачем юзать goto если в C# есть ключевое слово специально для нашей ситуации? Смотрим: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/statements/jump-statements#the-return-statement

            The return statement terminates execution of the function in which it appears and returns control and the function's result, if any, to the caller.

            As the preceding example shows, you typically use the return statement without expression to terminate a function member early.

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

            Вы также справедливо заметили, что я мало что написал по поводу самой статьи. Я скажу как читатель хабра что мне не нравится, когда в prerequisites для понимания статьи входит просмотр видео на ютубе. Моё ИМХО что статья должна быть самодостаточной, но без просмотра видео что эта, что прошлая статья больше запутывают чем объясняют. Но в этом конкретном случае я посмотрел видео, о которых идёт речь, и моё мнение что вариант в принципе рабочий в некоторых ситуациях. Хочется только спросить в чём преимущество такого подхода по сравнению с другими методами для решения такой проблемы? Мне кажется используя тот же Zenject решить проблему можно было бы гораздо меньшими усилиями.

            Теперь давайте к весёлой части)

            Вы сами понимаете, что этого мало? Что как минимум в раза 4 это меньше моего?

            Да, я понимаю что 5 лет это меньше чем 20. А ещё я понимаю что это имеет абсолютно нулевое отношение к поставленным вопросам. Аргумент "я прав потому что у меня 20 лет опыта" это обычный аргумент от авторитета, являющийся подвидом ad hominem на который вы жаловались в соседнем комменте.

            Во всех компаниях где я работал всегда поощрялось когда начинающие ставят под вопрос действия синьоров. В 9 из 10 случаев синьор окажется прав, объяснит новичку почему он прав, новичок за счет этого поднимет свой технический навык, что хорошо для компании. В 1 из 10 случае синьор окажется неправ (нет людей которые не ошибаются) и код попадет в проект только после исправлений, что также хорошо для компании. Win-win. А за аргументацию вида "делаем так потому что у меня N лет стажа" синьора ждал бы как минимум разговор с HR.

            Что это за манера такая, не зная оппонента думать, что он знает меньше вас?

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

            И нет, вы позволили себе - учить меня тому, чего я не просил!

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

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

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

            Я для пояснения своей позиции вернусь к базовому вопросу: в чём заключается суть работы программиста, применительно к геймдеву? По моему убеждению, все сводится к тому что мы должны написать продукт, который приносит стейкхолдеру максимум $$$, при минимальных затратах $$$ самого стейкхолдера. Для программиста достижение этой цели держится на трех столпах:

            1) Умение эффективно коммуницировать как с техническими, так и с нетехническими коллегами.

            2) Умение создать удобную, адекватную, расширяемую архитектуру.

            3) Умение писать код чисто и понятным/принятым в компании стилем.

            Убери один столп - и стейкхолдер начнет терять $$$.


            У вас чистый код, но плохая архитектура? При добавлении новой фичи придется муторно/долго её подключать, и стейкхолдер потеряет $$$.

            У вас хорошая архитектура, но код стайл плохой/не соблюдается? При ротации новичка на проект он будет первые несколько месяцев с головной болью плутать в куче вложенных ifов и ветвящихся методов, и стейкхолдер потеряет $$$.

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

            Со всех сторон хороший фидбек, и программист получает заслуженный рейз $ :)

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


            1. tac Автор
              13.06.2022 04:24

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

              Ох, пристыдил то как ... но единственной моей задачей было сбить спесь, и заставить не писать так безапелляционно, таким как вы ... Теперь, когда вы еще кому ни будь напишите про коде стайл, пишите именно так (сделаю вам win):

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

                • Да, я в такой работаю ..

                • "Зачем два раза писать имя класса? Визуальный мусор " - это глупость в том месте тип не написан, во время рефакторинга необходимо многое править в зависимости от типа, наличие var - очень сильно замедляет рефакторинг, а тут я могу по праву сослаться на опыт :)

              2. "Она не лишняя, её предназначение - удобочитаемость. "

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

                • Дальше откройте, книгу "Балена Ф. и Димауро Д. - Современная практика программирования на Microsoft Visual Basic и Visual C# - 2006"

                • Но это (Фаулер) входит в противоречие с правилом 12.25 - но в моем случае и не было, как минимум длиной вложенности

              3. "Это наверное самое субъективное из всего списка. Вариант с явным сравнением с false сильнее визуально нагружает, на мой взгляд. "

                • Как не странно, но правило 18.9 за ваш подход. Но, в случае конкретно этого случая - там не простое сравнение с переменной в моем случае (вы то ввели бесполезную), поэтому, тут мне надо писать , имхо, знак ! плохо виден в отличие от единообразного сравнения с == flase / == true (да, и слова "сильнее визуально нагружает" - надо воспринимать так, что для этого то я это и делал)

              4. О return - Правило 14.16 Единственная точка выхода ... тут вам надо просто подучить мат. часть

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

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

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


            1. tac Автор
              13.06.2022 04:41

              Мне кажется используя тот же Zenject решить проблему можно было бы гораздо меньшими усилиями.

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

              Но давайте так, я уеду на 2 недели, а вы реализуйте биндинг на Zenject  - вы же это предлагали? А я приеду почитаю, покритикую, сделаем win-win :) ?


        1. tac Автор
          12.06.2022 14:40

          Да, еще мини урок для любителей схлопывать условия, типа

          if (Related != null && !IsDoneBinding(behaviorName))

          не делайте так никогда. Код должен быть удобен для рефакторинга, условия это одно из главного, что часто меняется. Понятно когда условие вложено в условие это аналог && но во-первых, это становится не так при наличии else. А во-вторых, и в главных, условия должны быть атомарными, относится к одного рода проверке. Здесь они о разном Related != null - это есть ли партнер для связывания, а IsDoneBinding - был ли биндинг сделан.

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

          Что собственно и было в моем коде, я писал, что он сложнее, и я его упрощал ...


    1. rundll32
      13.06.2022 19:55

      Чем ваш первый пример цивилизованнее, кроме того, что он короче, и что так проще допустить ошибку, не заметив отрицание?


  1. tac Автор
    12.06.2022 00:43
    -1

    Ну, и раз зашла такая тема. Некоторые наблюдения.

    2 курс. Без разницы как писать код, лишь бы работал ...

    5 курс. Начинаешь верить в какую-то идеализацию. Вырабатываешь свои взгляды на стиль ...

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

    5-10 лет. Отстаешь от других и просто кодишь сам в том стиле который нравится тебе.

    10-15 лет. Не позволяешь другим себя переучивать. Идешь лишь на мелкие уступки.

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

    17-18 лет. пофиг какой стиль, читать можешь что угодно, но если скобки стоят не так как нужно - не понятно что написано.

    19-20 лет. увольнять если используешь пробелы вместо табов - кажется правильная идея :)


  1. arTk_ev
    12.06.2022 19:25

    В MVVM главное - это забиндить поля vm к view, а не наоборот. Делается это для упрощения логики и независимости компонентов и ивентов. А View смысл биндить есть только если вьюха на xaml. Легче использовать тот же unityevent