А что если бизнес в наше время ускорился до таких скоростей, что классический способ построения приложений уже не о правдывает себя. Мы возложили на команду разработки беклог, и ждем когда они его реализуют. Что если разработчики приложения должны подумать о том, чтобы создать конструктор на базе своего приложения, и дать возможность пользователям кастомизировать свой UI/UX по их потребности. Пусть будет базовый интерфейс приложения by-default используемый неподготовленным юзером. Но для подготовленного юзера всегда будет возможность залезть под капот и настроить любой скрин этого приложения кастомно. Да это будет более сложное взаимодействие, чем мы привыкли в Web 2.0 и скорее всего придется выучить тот или иной скриптовый или декларативный язык конфигурации этого приложеняи конструктора. Пользователю не надо ждать, когда команда разработки закончит свой беклог, им уже создали конструктор - надо лишь только разобраться как что устроено и сделать свою кастомизацию.
Я все свои pet проекты пишу теперь такими конструкторами. Всегда есть некоторый скрипт/конфиг, который позволяет без перекомпиляции приложение поменять его свойство. Даже в этом блоге есть зародыши такой возможности - могу использовать режим верстки, или погрузиться в увлекательный мир HTML и сверстать все по-инженерному. Уверен множество приложений имеют такой advanced тулинг стоит присмотреться. Я лишь рекомендую довести это до максимума и внедрить новый подход в разработку ПО. И дело не только в обработке данных, которые передаю на вход из фронтенда в бекенд. Можно пойти дальше и дать возможность влиять на бизнесс логику.
Может показаться, что это не безопасно. Открывая больше дверей мы делаем более уязвимыми наши сервера. Но сейчас могу так же открыть Inspect вкладку браузера и на любой страничке посмотреть множество запросов и выполнить большую часть из их независимо от других. Могу написать свой UI поверх существующего API. Часто разработчики сами открывают свои API и документацию на него. Но это не совсем то, что предлагаю. Я хочу иметь возможность влиять на то как будет работать мое приложение путем задания сценария бизнесс логики.
Возьмем например этот блог. В нем есть ряд скринов, где-то в настройках могу настроить блог включая или выключая определенные фичи. Я могу настроить внешний вид всех страничек в конструкторе. На этом этапе мне не нужно еще быть инженером - все достаточно визуально.
Так кажется, стоит мне отредактировать любой блок, как я тут же увижу html/js/css код.
То есть если я лезу в настройки приложения, я вероятнее всего должен быть инженером.
Если посмотреть в другие настройки - я могу так же изменить HTML в который все будет собираться в результате.
Это то о чем я говорю. Но опять же очень глубоко спрятано и сделано достаточно сложно. Сложно в обе стороны. Для разработчиков скринов настройки блога это еще один скрин, который стоит времени разроаботчика - взять тот же drag & drop конкретных блоков. Надо ли это мне инженеру? Ну мне было бы проше отредактировать текстовый файл конфигурации. Надо ли это юзеру без навыков кодирования? Скорее всего он сюда не доберется, а добравшись будет делать что-то что ему расскажут в видео мануале или посте в блоге, который он нагуглит - "...хотите добавить кнопочку с рассылкой, скопируйте этот текст и вставьте его сюда...". Мне же этот скрин не позволяет сделать чуть больше, чем позволено. Там есть зашита общая структура блога: сверху navbar, ниже crosscol, потом идут основной main и справа от него sidebar. Я уверен что и этот темплейт где-то зашит в коде. Я бы хотел иметь возможность редактировать его.
Но если мы пойдем дальше. Вот у меня есть список постов в блоге. И я хочу его видеть в другом виде.Могу ли я сейчас повлиять на это? Нет
Пойдем дальше. Покусимся на бизнеслогику. После публикации поста он появляется в блоге, прием можно сделать отложенную публикацию. А что если я хочу тут добавить дополнительный флоу - скажем написать email или вызвать какой-то rest api чтобы сообщить о факте публикации? А что если я хочу иметь возможность так же делать какие-то полезные мне действия при каждом открытии поста читателем? Что если я хочу рендерить пост по разному, в соответствии с тем какое время суток? Что если я хочу не в html формате хранить мой пост, а в markdown? Что если я хочу хранить свои посты не в базе blogger, а на github? Могу ли я сейчас на это все влиять? Нет конечно. Потому я отправляюсь в opensource мир и ищу блог, который мне больше всего подойдет. А если не найду оного - сажусь писать свой конструктор.
Самая лучшая метафора того, как мне кажется будет уходить web в ближайшие годы - конструктор лего. Есть книжечка, где описано как построить домик с озером. Есть другая книжечка, в которой написано как построить космический корабль. И есть большой мешок с кубиками разных размеров. Пользуясь этой метафорой я предлагаю пользователю все в собранном виде вместе с этими книжечками, что дает возможность ему пользоваться функционалом сразу. Но если в будущем пользователь захочет пристроить лазерную пушку снятую с косчического корабля на крышу своего загородного домика с озером - у него есть такая возможность.
На сегодня все мои pet приложения так или иначе реализуют этот подход. И я могу сказать что это достаточно сильно меняет и подход в разработке и архитектуру. Когда вы делаете конструктор - все должно быть разбираемо и собираемо обратно, причем в другой форме. Детализация компонентов должна быть проработана в том месте, где требуется гибкость. Главная идея, чтобы при пересборке приложение все еще оставалось в изначальном домене: если это изначально был blog, то после переконфигурирования это будет все так же blog, а не какая-то скажем crm. Решить, где добавлять конфиг, что бить на компоненты, насколько мелко декомпозировать, а что оставить проприетарным монолитом - хорошие вопросы.
Сейчас например я работаю над микросервисом по построению LLM цепочек для решения своих несложных задач автоматизации рутины с помощью LLM. Все эти цепочки вынесены в конфиг, который является кастомизацией yaml формата. Я слежу за тем, чтобы конфигурирование цепочки оставалось простым. Но все же без инженера в них не разобраться. Потому есть многочисленные демо решения - файлики с уже созданными цепочками, в которых делается что-то полезное, что может быть относительно быстро исправлено не инженером и реализовано под свои нужды.
Другой мой пет проект - CRM система ведения кандидата по воронке стафинга и онбординга на проект. Сама воронка состоит из шагов, каждый из которых описан в markdown и превращается в html страничку которую видит тот или иной коллега - кандидат, его менеджер, рекрутер, HR специалист и так далее. Все они делают на страничке что-то с данными, завязанными на этого конкретного кандидата - выступают consumer или supplier этих данных. Некоторые шаги могут быть пропущены в заивсимости от определенных conditions. Так как на разных проектах последовательность шагов может быть иной - я как delivery менеджер этого проекта настраиваю эту цепочку сам. На выходе я получаю отдельный проект с набором markdown страничек где описан весь флоу (что полезно для KT другому менеджеру кто прижет на мое место), я могу добавлять улучшения в этот флоу и видеть в git историю изменений. Будучи загружена в приложегние эта цепочка превращается в конкретные скрины, странички, поля ввода/вывода, формы, таблички, реакции на сторонние сервисы как то отправка email и так далее. Для этого мне пришлось добавить свои новые теги к существующим в markdown. Конечно же пиать этот скрипт воронки придется тому, кто по-инженгерному разберется в нем. Но я точно знаю, что delivery manager IT компании точно сможет найти в своей команде инженера-волонтера, кто поможет ему в этом разобраться в свободное от работы время.
Еще один pet проект - блог. Я хочу переехать с blogspot и писать посты в markdown. Я хочу иметь возможность концигурировать свой блог подобно тому, как описывал это в этом посте выше. Скажем я хочу иметь возможность разместить 1 линку на youtube видео, и настроить в конфиге фильтр, который в зависимости от ссылки на видео будет вставлять либо youtube embed html блок, либо подобный блок другого видео хостинга. Причем я хочу описать это один раз и в одгом месте, а не копипастить постоянно этот код в каждый мой пост. Я хочу сохранять мои посты в git репозитории с версиированием, а блог система пускай поднимает его из git repo по моему запросу.
Другой мой проект Codenjoy хоть и не конфигурируется в скриптовом формате, но все же c самого начала позволяет создавать новые игрушки очень быстро. Все сделано для того, чтобы сегодня (максимум завтра) вечером появилась новая игра, если ты того пожелаешь. Да - тебе придется кодить на java. Но все API построено таким образом, чтобы это было максимально просто.
Люблю свой Сodenjoy проект потому, что могу в нем пробовать новые подходы в разработке. Сегодня хочу продемонстрировать один из них. Ведь именно так и рождаются инженерные практики: ты экпериментируешь на своей кухне => что-то показывает хороший результат => ты это осознаешь => публикуешь открытие => его уносят в массы.
Вот пример использования одного кастомного малого, которого я научил бегать по разным jar расположенным как в класспасе, так и за пределами проекта (рядом с war например в папке с плагинами).
@Configuration
public class MVCConf implements WebMvcConfigurer {
@Bean
@SneakyThrows
public ResourceHttpRequestHandler resourceHttpRequestHandler(ServletContext servletContext) {
return new ResourceHttpRequestHandler() {{
setCacheControl(getCache());
setLocations(Arrays.asList(
// only for testing so that you can get resources from src/target folder
new UrlResource("file:../games/*/src/main/**"),
new UrlResource("file:src/main/**"),
new UrlResource("file:target/classes/**"),
// production code
new ServletContextResource(servletContext, "/resources/"),
new ClassPathResource("classpath:/resources/"),
new ClassPathResource("classpath*:**/resources/"),
new UrlResource("file:" + pluginsStatic),
new UrlResource("file:" + pluginsResources)));
setResourceResolvers(Arrays.asList(new JarPathResourceResolver()));
}};
}
Тут можно заметить один интересный сайд эффект. Если во время разработки натравить его на папку src/target (чтобы он искал сперва там), то можно будет править скрипты и без пересборки приложения видеть изменения в браузере. Это секономит тебе дни времени за недели разработки. Достаточно будет отключить кеши в браузере или нажать Ctrl-F5.
Но вернемся к тестам для этого малого. Ничего примечательного. Все как обычно. Достаточно хорошо читаемо. Только меня смущает тот самый CopyPast который я всегда делал, чтобы создать базу для нового теста. А раз есть CopyPast, значит есть пространство для Рефакторинга.
public class JarPathResourceResolverTest {
private JarPathResourceResolver resolver = new JarPathResourceResolver();
@SneakyThrows
public String load(Resource resource) {
return StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
}
@Test
public void shouldLoadFromServletContext() {
// when
Resource resource = resolver.getResource("file1.txt",
new ServletContextResource(new MockServletContext(), "/resolver/"));
// then
assertEquals("ServletContext resource [/resolver/file1.txt]", resource.toString());
assertEquals("one", load(resource));
}
@Test
public void shouldLoadFromClasspath() {
// when
Resource resource = resolver.getResource("file2.txt",
new ClassPathResource("classpath:/resolver/"));
// then
assertEquals("class path resource [resolver/file2.txt]", resource.toString());
assertEquals("two", load(resource));
}
@Test
public void shouldLoadFromClasspathIncludingJars() {
// when
Resource resource = resolver.getResource("NOTICE",
new ClassPathResource("classpath*:META-INF/"));
// then
assertMatch("URL [jar:file:*.jar!/META-INF/NOTICE]", resource.toString());
assertEquals(true, resource.exists());
}
@Test
public void shouldLoadFromFileSystem() throws Exception {
// when
Resource resource = resolver.getResource("file3.txt",
new UrlResource("file:src/test/resources/resolver/"));
// then
assertEquals("URL [file:src/test/resources/resolver/file3.txt]", resource.toString());
assertEquals("three", load(resource));
}
@Test
public void shouldLoadFromJarsInFileSystem_case1() throws Exception {
// when
Resource resource = resolver.getResource("file4.txt",
new UrlResource("file:src/test/resources/resolver/*.jar!/resources/**/"));
// then
assertMatch("URL [jar:file:*/server/src/test/resources/resolver/jar4.jar!/resources/subfolder/file4.txt]", resource.toString());
assertEquals("four", load(resource));
}
@Test
public void shouldLoadFromJarsInFileSystem_case2() throws Exception {
// when
Resource resource = resolver.getResource("file5.txt",
new UrlResource("file:src/test/resources/resolver/*.jar!/resources/**/"));
// then
assertMatch("URL [jar:file:*/server/src/test/resources/resolver/jar5.jar!/resources/file5.txt]", resource.toString());
assertEquals("five", load(resource));
}
}
Не секрет, что я люблю использовать в своем проекте approvals подход. Единожды подглянутый на какой-то конференции много лет назад в одноименной библиотеке я сразу осознал, что мы с ним на долго. Больше не будет никаких assertEquals(42, godObject.getMainQuestion()); и последующих медитирований над одиноко слетевшим jUnit ассертом без понимания "а что там дальше было-то". Нет, я просто возьму и допишу объекту toString() метод (если не могу на проде - сделаю toString(godObject) в процедурном стиле прям в тестовом классе) и далее буду:
assertEquals("В книге Дугласа Адамса «Путеводитель для путешествующих автостопом по галактике»\n"
"ответ на «Главный вопрос жизни, вселенной и вообще» должен был решить все проблемы Вселенной.\n"
"Этого ответа с нетерпением ждали все разумные расы.\n" +
"Он был получен в результате семи с половиной миллионов лет непрерывных \n" +
"вычислений на специально созданном компьютере — Думателе.\n" +
"По утверждению компьютера, ответ был несколько раз проверен на правильность, \n" +
"но он может всех огорчить. Оказалось, что ответ на вопрос — «42».", godObject.toString());
Теперь, если у меня слетит тест, я буду видеть diff всего стейта объекта, а не малоинформативное "Expected: 42 But was: 43". Я всегда раньше думал глядя на такие ассерты как-то так:
На основе этого approvals подхода сделано много кастомных решений в проекте. Для Smoke тестов например я использую даже стенографию каких-то важных мне аспектов системы в плоский файл.
С последующим сравниванием двух файлов (expected / actual) с помощью встроенной в IDE diff тулы. Конечно этот файл никогда не правится вручную - я лишь смотрю на изменения которые он мне подсветил и либо approve (отсюда название подхода approvals) их либо лезу в код править что-то, что я не учел.
Так, пока diff не будет таким, который я ожидаю. Лишь тогда я смогу старый expected файл заменить новым actual, сгенерированным во время последнего запуска. Его я и закоммичу как новый expected слепок.
Но вернемся к инсайту сегодняшнего дня. Базируясь на этом подходе я пошел дальше и захотел переписать юнит тест в какой-то такой вид.
Все это может чуть-чуть напугать. Ведь во-первых формат непонятный. Во вторых посмотрите на эти строчки - кто будет потом суппортить такой длинный ассерт? Но спешу успокоить - я никогда не буду править этот текст ручками - буду копировать результат из diff тулзы в случае исправления и вставлять его между двух кавычек "". В этом суть approvals подхода. Я смотрю diff - я вижу, что отклик теста на мои исправления в системе адекватен, и я применяю actual как новый expected.
Каждая такая строчка одновременно и инструкция как запускать тестируемый класс (SERVLET - используй ServletContextResource, CLASSPATH - ClassPathResource, URL - UrlResource), и директивы как проверять результат (NULL - ожидается что ресурс не найден, EXISTS - не грузим файл полностью, а только проверяем его существование).
А если в блоке resource.toString() встречается "*" - то использовать не assertEquals, а assertMatch, который проверит соответсвует ли строчка "qwertyu" заявленному паттерну "qw*yu", что тоже удобно - потому как resource.toString() выдает часто полный путь включая c:\\java\\... что сделает тесты чувствительными не только к системе но и к местоположению проекта.
Короче сделал свой DSL и запаковал его прямиком в expected текст. Магия подхода в том, что выполнение этих команд сгенерирует точно такой же по формату actual блок команд, только с подставленными runtime результатами. А IDE останется только показать diff этих двух версий. И напомню, если мне понравится actual, я скопипащу его в expected теста. Если нет - я отправлюсь в код программы и буду править.
Например я тут я сразу вижу, что ServletContextResource работает, а вот с ClassPathResource и UrlResource беда - они все не хотят искать файлы.
А вот тут я вижу, что как-то криво контактенируется искомый файл и контекст в котором ищем и там появляется лишний слеш, а потому некоторые кейзы поиска не отрабатывают
Магия approvals подхода в том, что ты лучше компьютера понимаешь, что не так глядя на всю картину целиком, а не на какой-то слетевший ассерт в каком-то богом забытом тесте с несовсем удачным именем. Компьютер может провести все вычисления за тебя и сделать это молниеносно - тебе стоит лишь попросить. А анализ данных - работа твоя.
Захотел я это все потому, что мне захотелось проверить еще надцать вариантов запусков с разными комбинациями параметров, чтобы на 100% убедиться, что все отрабатывает окей. Но делать надцать раз CopyPast это черезчур. Потому я сделал небольшой тестовый фреймворк прям в этом тесте. Да он сейчас выглядит сильно менее читабельно.
Опять же, в чистом approvals подходе я никогда не пишу этот весь контент сам. Я запускаю пустой ассерт.
@Test
public void shouldAddTrainingSlash() {
assertAll("");
}
Далее копирую Actual из diff тулы IDE и вставляю его в пустые кавычки, но только если вижу, что там все ок. Если не ок - одно из двух: либо тестовый фреймворк с ошибкой, либо я нашел ошибку в продакшен коде.
Но в новом подходе надо указать какие-то директивы к запуску. Это обязывает использовать свой паттерн. Благо если уже есть какие-то наработки то Ctrl-D и скопировать строчку и поправить не сложно. А когда есть какой-то сет - дальше пользуемся CopePast Actual => Expected.
Кстати вот код, который генерирует это все безобразие.
Сложнее для поддержки чем оригинальные юнит тесты, согласен. Но единожды
отладив я практически никогда не лезу в него больше. Тут меня уберегает
другой подход в тестировании - я всегда стараюсь писать тесты на
публичный интерфейс выглядывающий за пределы пакета, а не на конкретный
класс. Я использую все преимущества юнит тестирования но в чуть более
интерационном разрезе. Тогда любой рефакторинг внутри пакета (реализации
его классов, удаление оных, создание новых) не влияет на такие тесты
почти никак.
Ах да! Надо назвать как-то этот подход. Имя твое - Directive Approvals Testing.
Все это было написано среди ночи под приятные слуху колебания воздуха в Patrik Pietschmann. Отдельно хочу отметить эту композицию другого Автора. Такое количества нот я не видел даже у Рахманинова, хотя тут больше гаммы, а у Раманинова тотальный рендом )
Кстстати небольшой бонус для тех, кто дочитал до этого места. Пример assertMatch как расширение assertEquals с проверками типа qwertyu == qw*yu. Очень полезно, если надо из expected блока скрыть часть текста, который либо очень недетерминированный либо выдает какие-то особенности dev-окружения закреплять которые в тесте конечно же не стоит.
String first = patterns[0]; if (!first.isEmpty() && !actual.startsWith(first)) { return false; }
String last = patterns[patterns.length - 1]; if (patterns.length > 1 && !last.isEmpty() && !actual.endsWith(last)) { return false; }
int pos = 0; for (String pattern : patterns) { int index = actual.indexOf(pattern, pos); if (index < pos) { return false; } pos = index + pattern.length(); }
return true; }
public static void assertMatch(String pattern, String actual) {
if (!isMatch(pattern, actual)) {
assertEquals(pattern, actual);
}
}
Ах да, этот код/и тесты был сгенерирован вредным ChatGPT, который все никак не хотел слушаться. Ему помог GithubCopilot в двух корнер кейзах. Будь внимателен. LLM моделям снится как они видели как кто-то кодировал когда-то. Именно этот "сон" ты видишь во время общения с ними. В их "коде" и любых утверждениях сосредоточено много ошибок, хотя сказано это с умным видом лица. Я бы сказал 60-80% информации верны - что уже очень-очень неплохо. На остальные % пиши тесты. Много тестов не бывает. О моем опыте промптинга я раскажу в другом посте.
Ах да, и делай Self Code Review перед каждым своим коммитом. Так, на всякий.
Находясь 6 лет в тени своих проектов https://dojorena.io и http://codenjoy.com, обучая других ребят проводить ивенты и отдавая им этот кайф взаимодествия с людьми я ограничивал себя ради более высокой цели. В эти годы не строил бренд собственный, но строил бренд компании, делая и продвигая продукт, который позволял рспостранять инженерный вайб многим. Десятки тысяч инженеров прошли через codenjoy-like ивенты. Это была моя миссия и фокус. И это время подходит к концу. Это была моя стратегия и моя большая ошибка - все это время должно было оставаться то, ради чего я весь этот уход в менеджмент затеял - что-то для меня.
Вчера был на Java ивенте и понял как я соскучился за всем этим организаторским. И первым делом сегодня утром написал ведущему ивента моему коллеге по компании чтобы "побалакать" про возможные будущие активности. Сошлись на том, что поделюсь опытом в прошлом и подумаем как быть. Поделюсь в свойственной мне манере - напишу пост в блог. Так как code reuse, а в будущем будет приятно посмотреть, перечитать.
Этот пост про былые заслуги. Много всего было. Но мне кажется сделано далеко недостаточно. Буду выкладывать не все ивенты, что были - их было много типичных. Интересно то, какими они были разнообразными. Так же надеюсь, что инженер, такой как я пытливый и зависимый, случайно попав на этот пост вдохновится и сможет разрешить себе отправиться в увлекательное public speaking путешествие. Начинать можно с малого. Так и распостраняется инженерная культура. От экспериментов в коде, через освещение в команде и на все большую сцену.
Первый опыт был в команде, когда меня менеджер попросил порисерчить очередной какой-то инструмент, типа JUnit (это было лет 15 назад). Я в этом разбирался для команды, перечитывая десятки статей, оставлял интересные 10% практические заметок в виде тезисов на бумажках подсказках, а потом и слайдах. Так я открыл в себе дар пользоваться метаформами для объяснения сложных штук простым языком. И то, что мне это все изучать чтобы потом поделиться очень нравится. Оказывается в XP есть такая отдельная дисциплина - метафора системы. Но это XP я открыл для себя позже. После успеха в своей команде мой опыт пошел по соседним командам. А сменив первую работу на вторую я сразу же подхватил идею моего менеджера делиться внутри команды code review замечаниями, но не peer-to-peer как это обычно принято, а с презентацией и командой в качестве слушателей.
Тут же с переездом в большой город для меня открылись многочисленные возможности - столько всего происходить, как бы успеть все?
Быстро понял, что ходить на конференции в качестве волонтера в разы интереснее и поучительнее, чем в качестве слушателя. Близость к организаторам, навыки в траблшутинге, близость к спикерам, препати (подготовка), афтерпати, афтер-афтерпати, нетворинг зашкаливал. Ходил не только на джава конфы, но и Agile и даже QA (именно на одной из QA конференций я понял, что QA это целый мир, не менее, а часто даже и более глубокий, чем мир DEV инженерии).
Первая моя рисованная преза на вебинаре, да и вообще первое выступление на большую аудиторию опять таки не будь я волонтером не познакомился бы с организаторами, не пригласили бы они меня сюда. Было страшно и это слышно, но я справился.
Там же познакомился с коллегой Сергеем Зелениным и понеслась наша eXtreme Programming коучинг практика. К тому времени я был на рельсах TDD и искал единомышленников в новой компании. Странно, но на всю компанию такой был только один Сережа. Так и подружились.
Десятки семинаров и авторских тренингов по TDD, для одного из которого с целью геймификации был придуман Tetris Dojo, ставший потом Codenjoy и задавший настроение всему что было после.
Авторский (наш с Сережей) проект Automated testing Dojo который потом, так же как Codenjoy, ушел в среду автоматизаторов т.к. мы все всегда отдавали в open source. Мы его придумали за пару часов (вот наше демо), а реализовали к ивенту еще через пару недель.
И много чего еще по мелочам. Все наши с Сережей выходные были распланированы на год вперед или в командировках или в подготовке к ивенту/тренингу/конфе. Это было чудное время полное обмена знаниями и поиске идеальной формы. Презы были скучные и километровые, потом веселые и вдохновляющие, было и LiveCoding, даже рисовали анимацию.
Все это могло быть на площадке GlobalLogic во время моей работы в тренинг центре компании. Там же я засетапил и поддерживал Moodle LMS с двумя тренингами J2EE и J2SE. Вел группу менторов для кодревью.
Закрывал роль XP коуча в командах после тренинга по TDD/рефакторингу.
Вел вместе с преподавателями пару лет c десяток групп студентов на площадке КПИ.
Организовал 2 ивента под ключ в Харькове для Java экспертизы с одним мессаджем - нечего слушать долгие заумные доклады, если слушаем то только в формате блиц 20 минут на спикера, а все остальное время нетворкаемся и делаем что-то ручками практически. Конечно же там был и мой доклад.
Перенял опыт проведения техтоков Глеба Рабылко их Харьковского офиса в Киевский и провел около 25 техтоков, 5 из которых были наши с Сережей (один из моих первых докладов там, слышно как я волнуюсь).
А вот как мы дурачились, поздравляя ребят в Харькове с их 50м техтоком. Дурачиться - это очень важно. Всякий треш будет происходить от людей хоть и ненамеренно но регулярно, а вот развлекаться - это надо форсить.
Выступал с от имени компании на стартаперском ивенте с Codenjoy. Занял второе место, наверное из за слов "у нас все хорошо, денег нам не надо".
С Владимиром Шиманским реализовали корпоративный HackerSpace и проводили уже на нем ряд ивентов, тогда как техтоками продолжила заниматься моя коллега по тренинг центру Татьяна Хряпина.
Чего только не приходило за почти 4 года работы в GlobalLogic - всему открывался. Потом сменилось руководство и стратегия тренингового центра. Было сложно объяснить человеку из позапрошлого столетия зачем это все и почему оно стоит того, чтобы тратить на это время и деньги. И мы разбежались.
Отдельно наверное стоит напомнить про опыт организации тусовки "Рекрутёры и программёры" когда на один ивент мы с Линой Шишкиной приглашали вместе представителей этих ролей, чтобы они друг другу объясняли простым языком сложные вещи. Рекрутерам это полезно, чтобы лучше понимать как хайрить ребят потом на рынке, а программистам понимание стратегий построения бренда, вилки зарплат, лайвхаки и так далее. Мне было странно, что никто не додумался до этого формата раньше и потому пришлось его изобрести. 5 встреч (кажется) хватило, чтобы запустить волну подобных инициатив на других площадках после чего продолжать не хотелось, т.к. миссия выполнена.
Далее был опыт построения оффлайн школы в стартапе GoIT. Поначалу это делали вместе с Сергеем Немчинским (сейчас Сережа продвигает свою школу и невероятно успешный ютьюб канал) но в последствии разделились, я ушел в построение программы и в помощи ведении остальных 10 групп а Сережа пошел в сторону своей школы.
Тут же было много ивентов маркетигновых но на тему Java и около IT (пуньк, пуньк, пуньк, пуньк, пуньк)
Так и внутри команд для поддержвания духа, например формат Hackenjoy был придуман как формат Hackaton + Codenjoy. Мы писали игры для уже тогда опенсорсного Codenjoy 48 часов. Так кстати было написано основное большинство ныне существующих игр.
Были и другие площадки не связанные с GoIT (пуньк и пуньк).
Был и первый опыт проведения вебинара - меня очень волновал онлайн я считал, что оффлайн плохо масштабируется и это одна из причин почему я ушел из GoIT спустя год.
Затем опыт построения своего стартапа и онлайн школы JuJa. Там я вдоволь насладился онлайном и вебинарами.
1000 часов моего вещания на ютьюб каналах (пуньк и пуньк - большая часть видео закрыта, т.к. мы это продавали, но в планах потихоньку сделать это всеобщим достоянием).
Организация воронки продаж онлайн бизнеса с партнерами.
Попутно все это организационное с написанием (уже в третий раз) тренинговой программы по java core + frameworks + soft skills.
А так как аудитория онлайн и доходимость до конца тренинга невелика, придумки всяких поддерживающих инициатив переродившихся в целую душевную не побоюсь этого слова секту свидетелей java )
Несколько организованных нашей командой конференций, где так же выступал сам (пуньк, пуньк)
Еще больше Letscode когда я просто включал IDE, микрофон и транслировал по принципу что вижу то и пою в эфир часами (пару примеров: пуньк, пуньк). Этот формат я случайно открыл еще в GoIT придя один раз на лекцию неподготовленный и признав это импровизировал по ходу. На что ребята сказали - так интересно наблюдать за решением проблем им еще небыло. Больше я не готовился ) В последствии вся JuJa построена была на этом знании. Ребята делали сами, а потом смотри как это можно было сделать еще. Плюс кодревью и продающие вебинары, которые так же разрезались на ролики по меньше и вставлялись в LMS в нужное место.
Были заказы из прошлых компаний на разбор таких штук как Groovy (пуньк, пуньк) и другие комерческие запросы реализованные в виде видосов.
Был повторно проведен формат Hackenjoy, но уже в онлайне. Игр было написано не так много как в офлайне, где я ходил и помогал всем, но зато был побит рекорд вещания (пуньк, пуньк, пуньк, пуньк, пуньк, пуньк)
Но так как бы небыло классно, мы подперли с командой потолок и больше не понимали как расти. Бизнеса
не получилось через 4 года устали и разругались с партнерами и больше
не продавали ничего. До сих пор плачу за хостинги, не поднимается рука убить контент. Но опыт был классный.
Так как параллельно с этим всем я проводил активно Codenjoy ивенты на всевозможных площадках. Вначале это был тетрис (пуньк, пуньк, пуньк, пуньк, пуньк). Потом появилась змейка (пуньк, пуньк). Дальше появился бомбермен (пуньк, пуньк, пуньк, пуньк, пуньк). Battlecity (пуньк). В общем понеслась... Так вот нас приглашали разные компании и в какой-то момент это сделала та самая, где я оставил 6 лет. Все ради нескольких сотен ивентов и десятков тысяч инженеров прикоснувшихся к этому чудному формату. Ивенты вначале пробовал проводить сам, а потом пришлось разивать движение Сенсеев, которые уже сами проводили ивенты на локациях. Так же на 4й год начал появляться продукт https://dojorena.io, как наш ответ на все возникающие запросы организаторов. Как выглядят dojo ивенты сейчас? (пуньк, пуньк, пуньк).
Вот такая вот история. Я не буду рассказывать в ней про мои кодинг активности на проектах, там было много и интересного-вдохновляющего и супер-скучного. Эти переживания (от увлечения до поытки сбежать) собственно и побуждали делиться потом с коллегами на всевозможных площадках. Но точно знаю - со скучным лицом ничего выдающегося не придумаешь. Дурачьтесь. Нудить успеется.
Сегодня возникла интересная задачка, ее хочу сохранить на память, т.к. уверен, что буду неоднократно использовать ее в будущем. А блог мой - это записная книга.
Предыстория. Есть большой Codenjoy репозиторий со всеми проектами: сервер, игры, клиенты к играм, скрипты для запуска, воспомагательные скрипты и так далее. Есть сообщество контрибюторов, и они делают форки. Иногда в этих форках они что-то полезное фиксят. Мне это надо в моем master. Я прошу их предлагать пулриквесты, но часто в этих пулриквестах содержится много всякого разного, что мне не очень надо в master - скажем изменения правил и дизайна под ивент, фиксы с которыми я не согласен. А так как все делалось наспех (ивент готовится обычно в свободное от работы время), то естественно контрибьютор не работал с веткой и может предложить либо все либо ничего. А мне потом выбирать коммит за коммитом. Брррр...
Задача. Разделить проекты на подпроекты так, чтобы с одной стороны у меня была возможность одной git командой (clone, pull, log, commit, push) работать сразу со всеми проектами; а с другой - принимать только те Pull Request что мне надо фильтруя лишнее. Читать дальше...
Сегодня решил залить новую игрушку от участника Hackenjoy Олега. По условиям участия - с участника игрушка, с нас кодревью с мерджем всей истории коммитов в общий репозиторий codenjoy.
Первую часть уговора выполнил еще неделю назад
А вторую вот только что закончил. На память о том, как мерджить два репозитория я оставлю тут заметку.
git clone дочернего репозитория который должен быть вмерджен в основной
cоздаем новый пустой репозиторий на github
в файле .git/config меняем путь со старого репозитория на новый пустой
git push --all ofigin
так что наполнили пустой репозиторий контентом
cd codenoy - перешли в основной репозиторий
git subtree add --prefix=CodingDojo/games2 https://github.com/codenjoyme/quadro-game.git master
далее переименовывем ручками папку CodingDojo/games2 в CodingDojo/games
и дальше в основном репозитории
git add CodingDojo/games2
git add CodingDojo/games/quadro
git commit -m"Добавили новую игру Quadro"
git push --all origin
В прошлой публикации я поделился анонсом мероприятия, который мы проводили уже дважды. В этом будет отчет.
Первым был offline ивент, когда я еще в GoIT развивал джаву в далеком 2015-08.
Вот коллажик из фоток
А вот более подробно о формате и заявленных игрушках ребят
В результате ребята получили бесценный опыт работы в парах (pair programming) а Codenjoy увидел около 15 новых игрушек. Не все их них были дописаны в тот день, но средняя готовность многих была около 90%. Реябтам судя по их отзывам очень понравилось. И я этому рад.
В этом году, буквально две недели назад мы стартовали online hackenjoy на площадке Juja. Формат изначально заточенный под offline экспериментально попробовали провести в online. И получилось! Конечно выхлоп не такой, как в случае, когда мы заперли участников физически в одном помещении на двое суток и не выпускали без реализованной игрушки, но все же очень здорово. И да мне самому удалось написать игрушку, которая вскоре появится на demo сервере.
Вот как это происходило в моем пространстве-время в трех частях.
Так же, как было обещано, для игрушек, что увидели свет - я записал активное кодревью с рефакторингом.
Как ты еще не знаешь? Это мероприятие на определенную тему, где собираются айтишники, чтобы за 48 часов реализовать прототип, который потом можно продемонстрировать всем участникам. Это очень фаново, поскольку все самое интересное происходит ночью. А под утро все ходят с немного измененным сознанием, что порождает массу креативных идей. Потом немного спят и снова за дело. Кодят все синхронно, кодят на одну и ту же тему, потому очень драйвово. Приблизительно как на стадионе во время футбольного матча или концерта :)
Что такое Codenjoy?
А это веселый тренажер для программистов. Там ты играешь в игру но не джойстиком, а с помощью своего бота, которого по ходу пишешь. Игр есть много разных. Змейка. Тетрис. Танчики. Бомбермен. 2048. Судоку. Кубик рубика. Хекс и так далее… Детальнее про Codenjoy тут http://codenjoy.com
А JuJa?
А это наша тусовка в которой мы часто проводим всякое-разное-интересное, в том числе рубимся в Codenjoу. Вот и возникла идея, а почему бы и да?!
И при чем тут я?
А при том, что на хакатоне ты будешь писать игрушку, которая возможно станет кандидатом в проведении финального турнира.
Но почему бы не использовать существующие игры?
Все просто. Игру необходимо держать в секрете, а все те, что уже есть - давно опубликованы. Это во-первых. А во-вторых игру надо хорошо продумать и хоть раз в нее поиграться всей командой.
Так что мы будем писать игры или играть в них?
Будем писать, а потом и играть. Все начнется на хакатоне, где мы двое суток стартанем написание игрушки. Попутно мы научимся таким штукам, как парное программирование и test driven development. Так вот мы стартанем, а потом у нас будет неделя времени, чтобы дописать игрушку, сделать ее максимально классной. На следующих выходных мы устроим финальный конкурс и мега баттл между разработчиками в эту игру-победитель.
Т.е. ориентироваться нужно на 2 недели свободных выходных? сначала 48 часов кодим игры, а на следующих выходных - ботов к игре-победителю?
Да, так и будет. Ботов кодят обычно 4-6 часов. На счет второго тура, думаю мы еще решим с ребятами, кто будет на первом. Чтобы было удобненько всем-всем. Так что главное запланировать первую итерацию - хакатон.
А что если про игру узнают?
Мы верим в то, что все что происходит в стенах Juja клуба остается в стенах Juja клуба. “Ведь, первое правило клуба гласит…” (с)
Шучу! Игра опенсорс. Движение открытое. Пусть узнают!
Стой, ты что-то говорил про TDD и парное программирование?
Да, драйвить ивент будет в том числе СанЁк Баглай, и он хочет на старте, дабы все было максимально эффективно, рассказать про правила парного программирования, правила TDD и сам Codenjoy фреймворк.
А если у меня нет напарника?
Не беда, можно будет напарника найти в группе участников. Главное зарегистрируйся. С другой стороны, если мы будем хакатонить онлайн, то можно и без напарника. Либо с напарником удаленно.
А как долго писать игрушку?
Если набить руку, то не сложную игрушку типа крестиков ноликов, змейки или пятнашек можно написать за 4 часа под ключ. Но так как мы это будем делать впервые, у нас будет почти 48 часов. Ну на самом деле эффективной будет только первая ночь :) Но самые крепкие из нас будут немного кодировать и на следующий день.
А если я приду уже с некоторыми набросками?.. :)
Наброски можно. Но вот вопрос в том, как написать правильно игрушку для codenjoy? Это все мы будем обсуждать в день хакатона. Есть ряд требований и фреймворк также подразумевает, что будут реализованы специальные интерфейсы. Мысли о том, какая бы это могла быть игра - это другое дело.
А если я не выдержу?
Ляг поспи и все пройдет. Ты можешь в любой момент закончить, если пожелаешь. В результате у тебя будет еще неделя чтобы закончить. Свет увидят те игры, которые автора допилят до конца.
Покидать локацию-трансляцию запрещено? :)
Можно, почему же :) Мы будем онлайн вебинарить, всегда можно будет отойти лечь поспать и вернувшись продолжить с того места, где остановились но с 2x скоростью :) При этом помним про напарника - надо будет с ним предварительно договориться. Ибо вы в связке.
Кстати про остальные игры, если игра-победитель будет одна, то что будет с остальными играми?
Каждая игра, что будет дописана включится (вместе с git историей) в codenjoy фреймворк (вот тут http://codenjoy.com/codenjoy-contest) с именами и фотками авторов (если разместите у себя в корне проекта описание) и в нее можно будет поиграть позже в любое время.
На какое время старта (и, соответственно, окончания)?
Стартуем в субботу утром, пилим до вечера воскресенья. И да, это будет не круглые 48 часов, а несколько меньше. Но этого будет достаточно - поверь :)
А где это будет?
Это будет онлайн. Можно локально собираться с ребятами по городам и коворкингам (для этого нужно самоорганизоваться). Запись будет. Я (Саша Баглай) буду кодить свою игрушку и транслировать это в эфир. К трансляции могут подключаться и другие участники (было бы любопытно понаблюдать как кто кодит). О технических деталях broadcast’а на youtube сообщим позже.
А можно взять друга?
Этот ивент не только для участников JuJa клуба, а для всех желающих. Потому приглашай всех, кого считаешь нужным.
А где найти напарника?
За этим вопросом в слак чатик. Важно чтобы вы могли в один день. Но если не получится - на месте мы создадим пары рандомно.
У меня есть вопрос, куда его задать?
Это Google Docs тут можно выделить любую часть текста и правой кнопкой мыши -> комментарий. А там задать любой вопрос.
Когда это будет?
Точные даты -
Во сколько начало?
первый этап - начало в 10:00 в субботу, а заканчиваем в 18:00 воскресенья
второй этап - известно
Как это будет происходить?
1 этап - подготовка, вы настраиваете окружение у себя дома, до хакатона, продумываете игру
2 этап - хакатон - тут мы разбираемся как писать игрушку, обсуждаем TDD и стартуем
3 этап - всю неделю до выходных есть возможность допилить свою игру
4 этап - следующие выходные выбираем лучшую игрушку и играем в нее
Ну а если ты еще не участник JuJa комьюнити, пиши нам на почту info@juja.com.ua Так же в процессе регистрации ты указываешь свой email и на него ты получишь все инструкции.
А можно поучаствовать в первом этапе, но не участвовать во втором? есть ли смысл?
Участвовать в первом И/ИЛИ во втором есть смысл. Что получишь? FUN Вот пруф http://codenjoy.com/portal/?p=58 Если будешь писать свою игрушку - оставишь след в истории. Что еще получишь - попробуем Test Driven Development и будет кодервью каждой игрушки.
Какие цели всего этого?
Цели у нас две:
1) Участники Juja комьюнити получат фан в процессе написания игрушек
2) Codenjoy получит много новых игрушек, а так как он крутится 24/7 то в них всех потом можно будет играть и играть.
win-win
А в резюме можно будет этот опыт записать?
А то! Можно конечно. Как участие в opensource проекте. Кстати да, сразу же работай из под своего github аккаунта, сделай форк https://github.com/codenjoyme/codenjoy-game - так ты навсегда останешься в истории проекта как соавтор.
А игры могут быть какие-то варианты настольных или нынешних мобильных пазлов? или все ограничиваемся 8-битными аналогами?
Игры можно писать любые. Есть особенности. Игра должна быть дискретной. То есть любое поле должно быть как в тетрадке в клеточку. Также игра пошаговая. Каждый тик - 1 секунда. Играют либо каждый на своем поле, либо все на одном. За 1 секунду все должны сделать свой шаг. После чего игра пересчитает состояние поля и посылает каждому клиенту новое состояние борды. И снова будет до 1 секунды ждать хода игрока.
Игру также можно кастомизировать. Например игра в крестики нолики - поле три на три, два игрока играют. Но мы ведь программисты. Можно сделать поле 10x10 и играть будут все кто хочет. Важно только понимать, за что давать очки. И чтобы в игру было интересно играть - то есть писать бота
Что надо будет написать кроме игры?
Под ключ. Движок игрушки, которая будет реализовывать интерфейсы codenjoy фреймворка. Мануал как играть в игру. Логику подсчета очков. Default’ового бота, который будет развлекать играющих (чтобы они бидоси сами не играли). Спрайты - квадратные png файлы, которые будут отрисовываться на поле.
Что такое спрайт?
Спрайт гуглим тут https://ru.wikipedia.org/wiki Это рисуночек квадратненький на котором изображены все возможные состояния живности на карте, дабы потом отрисовать на поле.
Спрайты могут быть статические - просто картинка, и анимационные - набор картинок (как гифка)?
Спрайты статические. Не надо усложнять, клиенту потом это все парсить. Если герой - то один символ. Если важно показать его направление - можно 4. Больше не стоит. По одному маленькому квадратику на какой-то элемент. В проекте есть sample игра, в ней реализована примитивная логика, но все рабочее. https://github.com/codenjoyme/codenjoy-game
В этом блоге я делюсь своим опытом. Не стоит пробовать ничего из того, что тут описано - это может быть вредно для вас или окружающих вас людей. Ответственность за применение любой из идей, описанных в блоге - всецело лежит на читателе.
Перед тем, как продолжать читать этот блог внимательно прочтите это сообщение.
Email рассылка
Нравится статья?
Как найти статью в блоге?
Я юзаю для этого google, в который я ввожу два слова "а пофиг" и что-то из того, что ищу - так быстрее. Пример