GameDev Architecture
1.22K subscribers
3 photos
2 files
74 links
Привет! На канале я делюсь своими заметками о том, как игровым компаниям строить правильные, эффективные и красивые решения, в основном на C#.

Рекламу не размещаю
Download Telegram
Похоже что coding bootcamps все набирают популярность. На западе — больше, чем у нас. Тем не менее.

Что же это может значить? Думаю то, что программирование набирает популярность. Многие хотят такой jump start. Чтобы вжух — и ты работаешь девелопером.

Проблема заключается в том, что не возможно за несколько месяцев освоить наше ремесло. Нужно постоянно учиться.

Количество разработчичков растет. Посмотрите на эту интересную инфографику выше https://t.me/poisonous_johns_lair/21.

Что тому причина? Высокий оклад? Востребованность? Успех стартапов Whatsapp, Uber и прочих?

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

Резкий рост неопытных разработчиков может быть проблемой. Ведь в идеале, на каждого неопытного разработчика — должен быть старший, который обучит его ремеслу.

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

Конечно же и в JS мире есть опытные и уважаемые люди. Но я думаю именно веб страдает от роста популярности программирования. Ведь порог вхождения гораздо ниже.

Вот такие вот у меня двоякие чувства.
Channel photo updated
Компания Apple сделала очередной неожиданный для меня ход — заопенсорсила ядро iOS и macOS.
Значит ли это, что Apple, вслед за Microsoft, пойдет по пути Open Source?

На самом деле, это не первый их шаг в сторону открытого ПО. WebKit и Swift — довольно известные опенсорсные продукты.

https://techcrunch.com/2017/10/01/apple-open-sourced-the-kernel-of-ios-and-macos-for-arm-processors/
Привет!

У меня много мыслей, которыми я хотел бы поделиться, но все они на разные темы.

Какую тему вы бы предпочли преимущественно видеть на этом канале?

Пожалуйста используйте ссылку ниже, чтобы проголосовать. Не забудьте нажать Start :).

/1. 🎮 Game Development
/2. 👍 Software Development (Quality of Code, Best Practices, Architecture)
/3. 🤔 Career Advices (как быть хорошим разработчиком)
/4. 📃 Новости в индустрии (компании, технологии, библиотеки и т.д.)
/5. ☝️Философские рассуждения на тему жизни разработчика, роли технологий, будущего и т.д.

http://telegram.me/PollBot?start=LTE4ODIxMTE4OTo1NWJlMzBhMzliYmJkMDE4Mg==
Итак, в голосовании победила тема Software Development, поэтому основная часть моих постов будет посвящена именно ей.

Сегодня я хотел дать вам пищу для размышлений на тему разработки архитектуры ваших программных продуктов.

Как часто вы занимаетесь разработкой архитектуры?
Нет, серьезно! Как часто вы выделяете отдельную задачу по разработке архитектуры?

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

> Хороший продукт не делается в спешке.

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

Что я понимаю под здоровьем? Давайте рассмотрим пример.

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

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

Конечно же — это палка о двух концах. Но, думаю, идея понятна.

Как же избежать подобных ситуаций?

- Выделяйте время на проектирование архитектуры — да-да, это важно! Создайте себе отдельную задачу, согласуйте ее с менеджером. Поясните зачем это нужно. На выходе постарайтесь получить документ, который описывает почему вы приняли то или иное решение по архитектуре. Это поможет другим людям понять ход ваших мыслей и подхватить, в случае чего, вашу работу.
- Максимально декомпозируйте задачи — это поможет не упустить мелкие (но ресурсоемкие) детали и все уложить в голове
- Привлекайте коллег на ревью архитектуры — ведь коллеги могут увидеть то, чего не увидели вы. Могут задать неудобные вопросы, проверяя вашу архитектуру (да и вас) на прочность. Полезно привлекать коллег из других департаментов. Например, проектировать серверную архитектуру, подключая клиентских разработчиков, и наоборот. Это поможет быть "на одной волне", и прийти к согласию во многих моментах, таких как модели данных.


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

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

// refactor this mess.


- Создайте отдельную задачу с предложением варианта устранения проблемы.
- Поставьте менеджера в известность и обозначьте возможные риски (желательно упоминая насколько это опасно для бизнеса)
- Запланируйте время для работы над этой задачей. Если задача будет просто валяться в бэклоге, пользы от этого не будет.
- Делайте регулярное ревью пула задач по устранению технического долга.

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

Разработчик должен уметь доносить информацию до "бизнес-людей". В этом нет ничего страшного. Более того — это один из ключевых навыков.
Наткнулся на интересную презентацию про монады:

https://www.youtube.com/watch?time_continue=1461&v=vkcxgagQ4bM

Популярность функционального программирования (ФП) растет. Когда я беседую с адептами ФП, практически всегда от них исходит элитизм и толика презрения. Мол как можно использовать Объектно-ориентированное программирование (ООП), вот уж ересь какая.

Интересно, чем же ФП лучше? На самом деле ничем. ООП и ФП — парадигмы. Это просто инструменты. И применение инструмента — зависит от задачи. Не нужно все доводить до крайности. Программирование — не религия. На этот счет есть перевод неплохой статьи:

https://habrahabr.ru/post/201874/

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

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

Но вопрос монад такой же спорный. Это тоже инструмент. И он не всегда уместен. Как по мне, так работа с коллекциями в C# с помощью монад LINQ очень удобна. Так же я считаю неплохой концепт у RxJava. Идея для использования архитектуры для UI а-ля redux, у меня проскакивала и до знакомства с ФП. А вот программирование асинхронных операций с asynс/await мне кажется удобнее.

А какова ваша история? Пишите (ссылка в описании канала), интересно услышать :)
Собираетесь менять работу? Нет? Ну может будет интересно. А может поделитесь с миром своим опытом...

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

1. Действительно хороший материал, из которого можно много подчерпнуть.

2. Там есть интересные подборки различных вопросов из top-tech компаний https://github.com/yangshun/tech-interview-handbook/blob/7870a58b31069c2f25b95b2529dfe5c082e05785/non-technical/behavioral.md

3. Это Open Source, это коллективное мнение. Туда можно контрибьютить и/или спрашивать вопросы, просить дополнять.

4. Может вы активно собеседуете людей? Это возможность вспомнить как это выглядит с другой стороны. А может даже поделиться своим опытом по этой части https://github.com/yangshun/tech-interview-handbook/issues/55

https://github.com/yangshun/tech-interview-handbook
Интересный анализ топа контрибуторов в опенсорс проекты. С данными можно поиграться в DataStudio самому.

Что забавно, MS среди лидеров. Подумал бы, что статья не объективная, но автор — Developer Advocate @ Google. Одно дело, когда MS говорит что является топ контрибутором, другое дело, когда это признают соперники. В интересные времена живём, товарищи.

Опенсорс позволяет делать потрясающие вещи. И даже такие гиганты как MS признали это и активно используют.

https://medium.freecodecamp.org/the-top-contributors-to-github-2017-be98ab854e87
Ранее я писал о том как полезно знание шаблонов проектирования, и как оно все может поменять.

Один из ключевых шаблонов, которые изменили мое мировоззрение в ООП мире был Dependency Injection. И это поистине великолепное решение.

Если вы не знаете что это за шаблон, то самое время это исправить.

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

Стандартный подход для устранения зависимостей — использование интерфейсов. Интерфейс позволяет отвязаться от конкретной реализации. А это дает свободу дейсвий и гибкость. Но подход должен быть конзистентным на всех слоях архитектуры.

Представьте, что мы заинжектили интерфейс для взаимодействия с базой данных


void PerformSomeQuery(IDb db)
{
db.Exec("INSERT INTO blabla VALUES('bla', 'bla')");
}


Но что если метод Exec этого интерфейса выглядит следующим образом:


interface IDb
{
void Exec(SQLString query);
}


Проблема данного кода в том, что интерфейс вводит новую зависимость: SQLString — некий внутренний тип для IDb. Это большая проблема, так как имплементировать интерфейс IDb, не привязываясь к внутренним типам, не представляется возможным. Что, по сути, делает данный интерфейс практически бесполезным.

В статье DIP in the Wild Мартин говорит о том, что

Высокоуровневый код не должен зависеть от низкоуровневых деталей

Чтобы избавить пользователя от головной боли, автор интерфейса должен так же использовать интерфейс


interface IDb
{
void Exec(ISQLString query);
}


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

Если это возможно, то лучше ограничиваться стандартными типами, и, например, заменить ISQLString на стандартный string.

В статье Мартина вы сможете найти много других интересных примеров и решений распространенных проблем.

Если вас интересуют подобные проблемы и тема проектирования архитектуры приложения, то очень советую книгу Clean Architecture
Действительно хороший справочник. Но чтобы таких ситуаций не возникало, не стоит хранить двухдневную работу не закоммиченной и не запушенной. Так же перед какими то серьезными операциями, я делаю локальный форк бранча. В случае чего можно будет все восстановить.

Вообще, не смотря на то что гиту уже куча лет, многие только-только попробовали его. Наверное, в каждой команде должны быть свои гайдлайны по работе с гитом, поверх общепринятых практик. В противном случае может случиться казус.
Forwarded from Spalmalo Tech Talks
Все же попадали с ГИТом в разные непредвиденные ситуации. С губ в такие моменты слетает многозначительный "упс", неприятно щекочет под ложечкой и начинают закрадываться мысли что последние 2 дня ты работал напрасно.
Вот тут https://github.com/k88hudson/git-flight-rules собрали планы спасения на такой случай. Да и просто рецепты, которые в повседневной жизни пригодятся.
Forwarded from Developers Community
Что использовать, знаки табуляции или пробелы? Или в этом нет разницы, потому что существует удобный инструмент? Читайте в нашей новой публикации.

Подробнее: https://habrahabr.ru/company/microsoft/blog/341722/
Думал что холивары на эту тему давно закончились, но нет. Автоматизировать процесс — выход. Такие языки как Go и Rust идут со встроенными форматами, поэтому никаких вопросов по этому поводу не возникает. Вот еще рамышления на тему стандартов кодирования: h
anonymous poll

Я за строгое соблюдение стандартов! – 21
👍👍👍👍👍👍👍 54%

Пусть форматтер делает всю работу – 16
👍👍👍👍👍 41%

Как хочу так и пишу, в топку стандарты! – 1
▫️ 3%

Мне все равно, просто пишу код – 1
▫️ 3%

👥 39 people voted so far.
Что-то voter не осилил все сообщение, потерялась ссылка:

Вот еще рамышления на тему стандартов кодирования: http://www.richardrodger.com/2012/11/03/why-i-have-given-up-on-coding-standards/
В последнее время часто сталкиваюсь с различными "платформенными" решениями, типа облачный PaaS. Решения клевые, мощные. Но...

Разработал какое-то решение с минимальным рабочим функционалом. Попробовал увеличить на него нагрузку и видишь что оно не справляется должным образом. Что делать?

Конечно же нужно оптимизировать. Первое правило клуба оптимизаторов гласит:

Никогда не оптимизируй вслепую

Это значит, что всегда нужно использовать инструменты профайлинга и делать замеры "до" и "после" оптимизации. Так же замеры "до" позволяют избежать ситуации, когда ты увидел далеко не оптимальный кусок кода, долго трахался с его оптимизацией, а потом оказалось, что тормозил то не он... 😫

И вот тут и вылезает проблема. Многие PaaS не имеют инструментов профайлинга и оптимизации. Поэтому приходится использовать годами проверенный метод научного тыка 👉☁️...

На самом деле это относится не только к платформам, но и различным библиотекам и фреймворкам
Как вы относитесь как платформенным решениям 📦 (Platform as a Service и другим решениям типа "черный ящик") ?
anonymous poll

Не пользуюсь. Хз что там внутри – 16
👍👍👍👍👍👍👍 43%

Пользуюсь. Нравится – 8
👍👍👍👍 22%

Пользуюсь. Не нравится – 5
👍👍 14%

Не пользуюсь. По другим причинам. – 5
👍👍 14%

Не пользуюсь. Боюсь вендор лока – 3
👍 8%

👥 37 people voted so far.
Софтварная разработка многогранна. Давайте немного отвлечемся от типичного веб-девелопмента и поговорим об испытаниях при разработке игр.

Я люблю Git, и предпочитаю использовать именно его. Но кодобаза игровых проектов очень большая. Не столько из-за кода, сколько из-за различных игровых ассетов (текстуры, аудио и т.д.). Проблема Git в том, что он хранит ВСЁ в локальной копии. А это значит, что он будет хранить и все версии ваших больших бинарных файлов.

Например, на одном из проектов размер всех файлов репозитория игры был 60+ Гб (исключая файлы истории). Теперь представьте размер репозитория, который должен хранить все версии на машине.

Эта проблема останавливала от перехода на Git и приходилось пользовать SVN. Ведь нужно было иметь и полную историю для кода, и все ассеты под рукой. Поэтому --depth флаг был не вариант.

Для новых проектов можно структурировать кодобазу таким образом, чтобы ассеты были в отдельном репозитории (сабмодуль), но вот переезд существующих репозиториев — большая проблема.

И вот теперь, Microsoft (опять удивляет!) объединился с Github чтобы внедрить поддержку GVFS [ http://www.gvfs.io/ ]. GVFS, как раз, решает проблему больших репозиториев. Ведь в Microsoft столкнулись ровно с тем же испытанием, но на кодобазе Windows.

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

Однажды я потратил целую неделю на поиск бага, когда мобильное приложение внезапно начинало жутко тупить даже в idle состоянии. Баг оказался в стороннем компоненте, который в случае потери сетевого соединения начинал спавнить кучу потоков!

Но есть случаи и похардкорнее. Забавный случай от инженера из Quora: https://hackernoon.com/solving-the-most-interesting-bug-of-my-career-in-15-steps-1a1ccd337c35

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

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

Поехали:

- https://engineering.riotgames.com/ — блог инженерной команды Riot Games (не знаете кто это? Разработчики League of Legends). Обзоры архитектур, конкретных технических решений и других вкусностей!
- http://highscalability.com/ — ресурс с кучей подборок и статей на тему масштабирования приложений
- http://horicky.blogspot.com — блог дата сайнтиста Ricky Ho с большим количеством тематических статей, написанных понятным языком
- http://tutorials.jenkov.com/software-architecture/index.html — неплохая подборка статей с кратким обзором основных архитектур и подходов в программировании
Вот уже много лет всеми правдами и неправдами программисты борятся с проблемами, связанными с null значениями. Tony Hoare назвал изобретение null reference для языка ALGOL W — "The Billion Dollar Mistake":

https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare.

И если в языках со сборщиком мусора это грозит всего лишь эксепшеном, то в с++ проблема может повлечь undefined behaviour (http://en.cppreference.com/w/cpp/language/ub) — штука, сулящая много часов безудержного веселья.

Некоторые изобретают свои костыли:

http://www.bfilipek.com/2017/10/notnull.html

Вопрос, зачем? Ведь в C++ есть reference, который не может быть null. Это и есть средство, позволяющее программисту выразить его нежелание возиться с null. Другой способ — Optional типы (std::optional в с++, Optional в Java).

В любом случае, стандарт языка имеет все необходимое для решения проблемы, причем compile-time. Так зачем же люди изобретают свои велосипеды?

Другое дело, когда в стандарте языка нет таких выразительных средств. Что делать? Приходится рассчитывать на средства статического анализа кода. Ребята из JetBrains любят такие штуки.

https://www.jetbrains.com/help/idea/nullable-and-notnull-annotations.html
https://www.jetbrains.com/help/resharper/Code_Analysis__Annotations_in_Source_Code.html

Но как по мне — это тоже так себе решение. Решение должно быть поддержано на уровне языка. Я уже говорил о том, что дизайн языка C# ведется в открытом формате, в репозитории github: https://t.me/poisonous_johns_lair/3. И это поистине потрясающее решение. Ребята действительно слушают коммьюнити. Вот, например, предложение по борьбе с Null:

https://github.com/dotnet/csharplang/blob/master/proposals/nullable-reference-types.md — proposal
https://github.com/dotnet/csharplang/issues/36 — discussion

Программисты — ленивые. Каждый раз проверять на null — большой геморрой. Так пусть это делает компилятор. Пусть он бьет нас по рукам за нашу лень 😃.

А как же быть тем, кто пишет на интерпретируемых языках или языках с динамической типизацией? Я забыл упомянуть о еще одном решении: монада Maybe — https://curiosity-driven.org/monads-in-javascript#maybe . Конечно, имплементации этого подхода не всегда удобны, но все же это может быть неплохим решением.
Привет и спрошедшими праздниками!
Надеюсь всем удалось хорошенько отдохнуть.

Наткнулся на такую забавную статью о буднях разработки Walking Robots, знаете такую игрушку?

https://habrahabr.ru/company/pixonic/blog/346374/

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

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

В игровой индустрии немного другая специфика. Если игрушка не взлетела — ее выкидывают и делают другую. Более того, даже на этапе прототипа ее могут по 10 раз переделывать так, что приходится начинать все с нуля.

Посему, "лучшее — враг хорошего". Перфекционизм — это болезнь. Хотя она и имеет положительное влияние, нужно уметь вовремя остановиться. И это важный скилл! Этот скилл является великим преимуществом.

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

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

Люди боятся рефакторить. А без рефакторинга проект обречен. Команде необходимы люди, которые смогут заниматься этим нелегким делом.

Рефакторинг должен быть частью цикла разработки. Он должен происходить каждую итерацию. А все задачи, связанные с техническим долгом, необходимо фиксировать в трекере, оценивать риски, и наблюдать, чтобы этот пул не разрастался.

Важно понимать не только "как" рефакторить, но и зачем, когда и где.

От себя могу порекомендовать прекрасную книгу от моего любимого Мартина Фаулера и других крутых перцев:

https://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672