Если нельзя, но очень хочется, то нужно обязательно и ничего в мире не стоит того, чтобы делать из этого проблему!


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

воскресенье, 31 марта 2013 г.

Вебинар Максима Фармера "Делаем бизнес на своем хобби"

Залез на Facebook и на стенке увидел приглашение на вебинар. А почему бы и да? На вебинаревидеоряда небыло, потому была возможность конспектировать за докладичком. Ах да, доклад подготовил Максим Фармер на тему "Как сделать из своего хобби бизнес?". Я слушал и записывал. Что получилось из этого всего  можно почитать ниже...

Почему именно на хобби? Хобби мы любим - хобби не бросим, даже, если будет сложно. Кроме того в хобби скорее всего ты эксперт - легче начинать...

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

Хрошо бы иметь напарника, который помог бы с бизнес-планом. Который сказал бы "вот тебе план, будут пробелмы - звони"... Где его найти? Вопрос риторический... Искать надо. Или самомугенерить...

Какие у тебя есть хобби? Самое главное определить, что имено нравится, чем ты будешь заниматься, скорее всего за бесплатно. У меня это: коучинг, программирование, мотивация людей, психология, фотография, путешествия, траблшутинг, поиск закономерностей, поиск эффективных путей, личностный рост... А у тебя?

Бодо Шефер спрашивает: что тебе нравится делать, что ты делаешь чаще остального и что делаешь уже прямо сейчас... Рекомендую почитать его книгу "Азбука денег"

Как монетизировать мои эти увлечения? Какой первый шаг? 

Взять листок бумаги и рассписать, что мне нравится делать и что я делать. Последний вопрос более важен, поскольку можно любоваться машинами, но ничего не понимать в них. Из любования, наверное можно заработать, но наверное сложнее... Выписать надо как можно больше (минимум 5, лучше 25). А потом понять - чем именно из этого я бы хотел заниматься бесплатно пол года-год. То, что останется - из этого обычно можно извлекать деньги. 

Как получить прибыль? Начать с сайта - визитки. Пример (http://showillusion.ru) там может быть всего три странички: Главная | Услуги | Контакты. Люди должны знать о тебе, люди должны знать, с чем они к тебе могут обратиться... Я такой-то такой-то, я готов сделать для вас то-то и то-то, вот мои контакты.

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

А еще стоит чаще выступать. Люди будут тебя видеть, потом звонить и спрашивать (быть может даже не по специализации)... Есть спросс - стоит подумать, что с ним делать. Но звонить так же будут из за того, что не все поняли и хотят, чтобы ты лично показал еще раз... А это уже за вознаграждение. Мы привыкли, что то, что нравится делается бесплатно - но ты тратишь свое время, а значит можешь запросить компенсацию его. А еще будут звонить для того, чтобы ты пришел и сам все сделал так же, как там на видео...

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

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

Мне тут вспомнился Саймон Синек "Люди покупают не за то, что вы делаете, а за то Зачем вы это делаете. А то, что вы делаете лишь доказывает это" Это поможет в продажах...
 
Я работаю гидом для людей потому, что ...................... но так случилось, что я люблю природу, а потому охота и рыблка это то, что вам сейчас предлагаю предлагаю.

Посещаемость не должна быть огромной. 30 посещений в день могут дать 15 уникальных, из них 5 проконсультируются, 1 купит... Хотя, зависит...

Рекомендуется так же ознакомиться с работами Александра Левитаса, в частности его "Партизанский маркетинг".

Можно пообклеивать объявления по городу. Можно даже попросить это сделать кого-то за тебя... Еще в процессе расклеивания объявлений тебе могут позвонить... Но расклеивая рекламу стоит задаться вопросами: А там есть мой потенциальный клиент? А как ему объяснить, что на самом деле это ему нужно?

Но перед тем, стоит подумать кто мой клиент. Проработать аватар. Как он выглядит? Какой у него рост? Какое у него хобби? Сколько ему лет? Где он работает.... И так далее. Чем больше, тем лучше... Чем конкретнее - тем лучше! Так же стоит понимать, что случаются такие интересности как "мужские бритвы покупают чаще женщины для своих мужей".

Разбирая какое-то направление, в котором мы хотели бы заниматься стоит начинать с вопроса - какая проблема есть у людей из целевой аудитории? Бренсторминг стоит включить на всю!

А что надо делать прямо сейчас, так это оторвать попу от дивана и взять самый первый таск из следюущего списка:

1) Сесть за листик A4, описать свои хобби и ценности, которые побуждают заниматься этим
2) Расписать как можно более подробно своего клиента (20-30 аттрибутов :)), а так же подумать надтем, чтоего парит, чем я мог бы ему помочь.
3) Прочитать книгу Бодо Шефера "Азбука денег"
4) Написать быстро простой сайт визитку
5) Создать быстро группу поддержки в соцсетях
6) Попросить быстро друзей попродавать меня
7) Расклеить объявления по городу или попросить это сделать
8) Подписаться на блог http://www.levitas.ru/
9) Пройти тренинг "Партизанский маркетинг"
10) Прочитать книгу "Больше денег от вашего бизнеса"

Вот такой вот любопытный вебинар от Максима Фармера.

Спасибо!

суббота, 30 марта 2013 г.

Вот она жизнь...

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


Машину мы все же оставили на аварийке, ибо, как оказалось, в баке было не много бензина, он стек на один бок и машина больше не завелась.


То что происходило было чудным - снег и тишина...

Домой я добрался пешком. Когда еще представится возможность в самом конце марта наблюдать такой снегопад... 

Это и есть жизнь - все то, что происходит, пока мы строим планы...


воскресенье, 24 марта 2013 г.

Mastering Public Speaking от Артема Сердюка 18 февраля 2013

Начну с благодарностей. Спасибо Диме Миндре за то, что пригласил меня на этот ивент. Спасибо Артему Сердюку за то, что подготовил его и провел. Ребята, вы сделали большое дело, так что хочется еще...

Хоть понедельник у меня был занят, но я очень хотел попасть и почистил первую половину своего дня. Хоть в воскресенье я засиделся по работе до глубокой ночи, и проспав всего два часа, мой организм все же пробудил меня без всяких будильников - так сильно я хотел попасть на ивент, который проводят Дима и Артем. Мне очень понравился их совместный Impact Map Dojo в прошлый раз на Agile Base Camp и я был уверен в том, что на этот раз будет еще более интересно! Тем более тема-то какая - Publick Speacking! И все получилось!...

Пришел я раньше всех, поскольку живу рядом с офисом Microsoft. Был только Дима и Артем. Это раньше говорили "во время", а сейчас это "раньше всех", хотя на моих часах было всего без 10 минут начало тренинга.  По-волонтерски помог расставить стулья и организовать working space - эту любовь мне привили волонтерства на конференциях от Scrum Guides. Спасибо им за это. И в течении надцати минут все было готово, а участники стали собираться... Не стал дожидаться, пока начнется официальная часть - первым стал знакомиться с такими же как и я сонными ребятами :) Утро понедельника, все таки... Потом понеслось....

Очень понравилось, что с самого начала Артем раздал каждому участнику пачку стиков с маркером, половину которых я исписал за 4 часа мастер-класса. Ведь если бы не эти следы, то сейчас, спустя неделю было бы сложнее написать этот отчет. Мне попались розовенькие :)


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

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


Кто же такой Толя? А Толя - это умный и опытный разработчик, который пришел скорее всего на шару (либо ивент бесплатный, либо компания оплатила) за "wifi и печенками". Толя очень любит троллить - он так развлекается. Ну и его можно понять - скорее всего это выходной день, он тратит его целиком и полностью на этот ивент - даже если ивент скучный, он найдет те вопросы, которые привнесут немного позитива в конференц, где сидят такие же заскучавшие как и он коллеги. Другое дело, что докладчик пострадает немного - но никто жеж не просил его в это субботнее утро выделяться из группы в пару сот человек и выходить на сцену... Скучно? Давай, до свидания...

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

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

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


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

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

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

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

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

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

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

В первом случае - "все вопросы в кулуарах" и все держится на харизме докладчика.

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

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

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


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

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

Так же понравилась идея вставки чего-то, на что точно отреагирует Толя "айфон фигня" ровно как "андроид фигня"...  Только вот опасно это :)

А еще покатит раздавать подарки, ведь Толя пришел за шарой :)

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

Но мне больше всего понравилось то, что после 20 минут работы сделал Артем. Он сказал, что это все хорошо, но это все фигня :) Нам не стоит развлекать Толю и вот почему....


Мы сделали приятный полумрак в конференце и стали смотреть доклад Саймона Синека о том, почему у одних идеи "покупают", а других продавцов игнорят. Вот он, этот доклад..


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

После этого Артем попросил нас уделить немного времени себе и написать на листочке А4 ответ на три вопроса:

- Кто я такой? 
- Почему именно эта тема важна для меня? 
- Для чего я готовлю этот доклад, каким будет результат? 

И тут все замолкли. Все стали писать о том, что для них по-настоящему важно. В тот момент в комнате чувствовалась магия. Артем сказал, что никто никогда не прочитает то, что мы напишем, вы это делаете для себя. Фрирайтинг рулит! Я отдался этому 10-минутному процессу и окунулся в глубину себя. Спасибо за это, Артем.

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

Что я еще понял? Понял, почему мне сложно найти тему для доклада, когда кто-то из организоторов приглашает выступить на конференции. Допустим нужна тема по Java - и кажется логичным, что практикующий и экспериментирующий Java разработчик/тренер имеет в загашнике множество тем. Но нет! Темы-то есть, но они не нравятся моей лимбической системе. Все, что меня вдохновляет из технических тем, о том уже давно рассказал, видео записал и в сеть выложил. Чего повторяться-то?

Но еще, что более важно, я понял о чем мне стоит готовить доклад. Тем таких сейчас три:
- Фрирайтинг как возможность общаться со своим личным джином,
- Как перестать думать и начать делать. Поиск спаринг партнера-дуала.
- Геймификация. Что наша жизнь - игра.

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

Что еще понял из сеанса фрирайтинг - зачем я это все делаю. А делаю я это (все наши доклады и не только) для того, чтобы тот Толя, который пришел послушать, ушел более свободным. Что значит "более свободным"? С мыслью о том, что где-то там внутри него Бесконечность и он готов начать пробовать. Не важно что, важно, что готов начинать... Ему не нужны команды инструкции, чтобы начинать... Ему не нужно еще чуть-чуть опыта... Ему не нужно завтра. Только Сегодня! - вот самое подходящее время для начала....

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

Доклад Саймона стоит использовать как пример вдохновляющего доклада. Его стоит разбирать по косточкам, что я и сделал сегодня лично для себя. Один прием мне понравился очень - он раз 10 повторил самую главную мыслю, с которой хотел бы чтобы участник ушел
Люди покупают не то, что вы делаете, а "зачем" вы это делаете. А то Что вы делаете просто доказывает то, во что вы верите. 
...и он апплаил эту мысль на несколько историй. Так же я записал себе в туду почитать больше про Мартина Лютера Кинга. И вот та его речь, о которой говорил в докладе Саймон, что начинается с "У меня сегодня есть мечта"...


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

Таких видео-сокровищ было еще несколько. Следующий докладчик, Kurt Vonnegut, рассказывал про то, какие истории любят люди. Смешной дядька :)


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

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


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

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

Мне на секунду показалось, что у Артема есть свое большое хранилище интересного видео контента - так он мастерски отвечал с помощью видео на вопросы участников...  Записал себе в туду еще, что стоит почаще смотреть доклады конференции TED...

Вот еще одно такое видео. Я не помню, почему Артем его показал, но оно клевое...


Делать ошибки это одно.... Клево, когда признаешь это...

Немного отвлекусь и оставлю тут пару идей, которые я записал для себя. Это мои якорьки:
- понравилось как Артем рисовал разными цветами на флипчарте. Стоит так же
- попросить кого-то из докладчиков-звезд сесть на первый ряд и записывать за мной у всех на глазах
- "мы идем туда потому, что мы так хотим..."
- "у меня есть мечта VS у меня есть план"
- "ты пришел сюда на работу не использовать то, что уже есть а менять то, что тебе не нравится"
- "чем дольше ты меня вводишь в свою историю, тем более бурной развязки я ожидаю от тебя"
- Todo: посмотреть фильм чужой. Вроде как ничего страшного в первой половине фильма нет, но всем жутко!
- "ты со мной не согласен, и это хорошо. Мы с тобой поспорим, но потом"
 - "есть ли какие-то правила, о которых нам сразу стоит договориться?"
- "предлагаю критиковать доброжелательно и конструктивно"
- "вы можете специально ошибаться, чтобы аудитория вас ловила на этом"
- "Кто герой? В чем конфликт?"
- Туду: еще раз поиграть с ребятами в игру по генерации бреда, при этом чтобы тебя отвлекали

Но пойдем дальше. Артем с самого начала тренинга, когда объявлял адженду сказал, что очень ждет этого модуля. Я себе записал в туду - делать так же. Пиарить то, что самое интересное в конце тренинга - это круто. Если до сих пор все было идеально, то что же в самом конце будет? А было вот что....

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

Дальше мы попробовали генерить бред в той же группе, на совершенно рендомную тему, причем двое напарников должны были уводить докладчика в сторону от его темы. Мне попался вопрос "Как пропатчить KDE2 под FreeBSD?" Зачем патчить? Все и так идеально начал я... Но Аким Бойко мастерски уводил меня от темы...

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


Дима Миндра держался идеально


А самое последнее задание, когда все не то чтобы отвлекали поднятыми руками, а вообще мешали докладчику вести его доклад. Цель докладчика не вестись на троллинг. Ууух!!! Дима снова на высоте!


На этом все. Надеюсь только пока. Детали по будущим ивентам на эту тему читай тут.

Спасибо Артем. Спасибо Дима. Спасибо участникам.

Хочется продолжения... Нями-нями...


среда, 13 марта 2013 г.

Какая фигура лишняя?

Утром попался на задачку


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

 
Мне настолько любопытно какой ты придумаешь ответ, что создал вот этот опросник

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

Вот, что подумлаось мне.

На самом деле не так важно, какой правильнй ответ. Но все почему-то его ищут.
Наверняка где-то там есть правильный ответ по мнению того, кто создал головоломку.
Наверняка есть какая-то идея у того, кто написал этот текст "что мол 90% проти 10%"

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

Много ответов, это работа интуиции. Брейнсторм - это связь акт общения с подсознанием.
Логика ничего нового не придумает.

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

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

Больше идей лучше, чем одна правильная.
Одна личная ошибка лучше, чем 10 подгядываний в ответы.
Свое мнение лучше, чем то что написано в книге или говорят умные дяди.

Выстреливает не логика, а новое использование старых предметов. А тут надо быть нелогичным.
Логика потом может заключить - "Да, точно! Как я до этого не додумался. Логично ведь!"

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

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

Как-то так...

воскресенье, 10 марта 2013 г.

JUnit хитрости: Ассертим все и сразу

Вот как часто пишут пользовательсвие ассерты.
    @Test
    public void test() {
        snake = new Snake(50, 50);

        assertHeadAntTail(50, 50, Direction.RIGHT, Direction.LEFT);
    }

    private void assertHeadAntTail(int x, int y, Direction headDirection, Direction tailDirection) {
        assertEquals(headDirection, snake.getDirection());
        assertEquals(tailDirection, snake.getTailDirection());
        assertEquals(x, snake.getHead().getX());
        assertEquals(y, snake.getHead().getY());
    }
Их недостаток в том, что если слетает первый, то мы не увидим всей картины - остальные не отработают. Этот антипаттерн юнит-тестирования называется "Заяц" - обычно чтобы не писать несколько разных тестов, мы просто подселяем к существующему тесту еще один ассерт. Кстати тут пахнет даже имя метода - assertHeadAndTail :) но проигнорим на минутку этот запах.
Можно изворачиваться так, как я это делал раньше. Но сегодня придумался другой способ, более легковестный.
    @Test
    public void test() {
        snake = new Snake(50, 50);

        assertHeadAntTail(50, 50, Direction.RIGHT, Direction.LEFT);
    }

    private void assertHeadAntTail(int x, int y, Direction headDirection, Direction tailDirection) {
        assertEquals( "[headX, headY, headDirection, tailDirection]",
                asString(x, y, headDirection, tailDirection),

                asString(snake.getHead().getX(), snake.getHead().getY(),
                        snake.getDirection(), snake.getTailDirection()));
    }

    private String asString(Object...args) {
        return Arrays.asList(args).toString();
    }
Слетает так
junit.framework.ComparisonFailure: [headX, headY, headDirection, tailDirection] 
Expected :[50, 50, RIGHT, LEFT]
Actual   :[50, 50, RIGHT, DOWN]
 at com.codenjoy.dojo.snake.model.SnakeDirectionTest.assertHeadAntTail(SnakeDirectionTest.java:72)
 at com.codenjoy.dojo.snake.model.SnakeDirectionTest.test(SnakeDirectionTest.java:36)
Меня устраивает!
Вот если бы только можно было бы находясь в методе получить список его параметров в текстовом виде, чтобы не писать вот так "[headX, headY, headDirection, tailDirection]" в каждом новом ассерте - было бы вообще идеально. Но эту головоломку остави на потом...

пятница, 8 марта 2013 г.

Бомбермен: немодифицируемый но синхронный список бомб

Самый главный объект в Bomberman - это доска, на которой происходит вся игра. Доска имеет ряд public методов, один из которых - дай мне все бомбы на поле. В первой версии он был простой как двери и потому небезопсный.
    public List<Bomb> getBombs() {
        return bombs;
    }
Вернуть копию списка - не вариант, поскольку, получив список на руки, я как клиент смогу воздействовать на бомбы непосредственно, меняя ход истории.
    public List<Bomb> getBombs() {
        return ListUtils.unmodifiableList(bombs); // из apache commons collections
    }
Тогда стоит итерироваться по всему списку и пересоздавать все бомбочки
    public List<Bomb> getBombs() {
        List<Bomb> result = new LinkedList<Bomb>();
        for (Bomb bomb : super.getBombs()) {
            result.add(new Bomb(bomb));
        }
        return result;
    }
Но тут другая задача. Те бомбы, что я скопирую рассинхронизированы с игрой - у них таймер замер сразу после копирования.
    public Bomb(Bomb bomb) {
        this.power = bomb.power;
        this.x = bomb.x;
        this.y = bomb.y;
        this.timer = bomb.timer;
        this.affect = null; // бомба - муляж
    }
Копирующий конструктор мне в помощь! Он кроме того, что копирует необходимые свойства, еще и подписывает копии бомб на события, которые получает оригинальная бомба. Для этого был создан наследник, чтобы не влазить в работающий Bomb.
public class BombCopier extends Bomb {

    private List<Tickable> copies;

    public BombCopier(int x, int y, int power) {
        super(x, y, power);
        copies= new LinkedList<Tickable>();
    }

    public BombCopier(Bomb bomb) {
        this(bomb.x, bomb.y, bomb.power);
        this.affect = bomb.affect;
        this.timer = bomb.timer;

        if (bomb instanceof BombCopier) {
            BombCopier copier = (BombCopier)bomb;
            copier.copies.add(this);
            this.affect = null; // бомба - муляж
        }
    }

    public void tick() {
        for (Tickable bomb : copies) {
            bomb.tick();
        }
        super.tick();
    }
}
Теперь еще усложним себе жизнь!

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

Любопытно, как это у меня получится!

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

Итак, мне надо вернуть List но необычный, а синхронный с оригинальным. Хехех :) Но в начале тест, которй скажет что все ок, когда я это сделаю...
    @Test
    public void shouldReturnShouldSynchronizedBombsList_whenUseBoardApi() {
        bomberman.bomb();
        bomberman.right();
        board.tact();

        List<Bomb> bombs1 = board.getBombs();
        assertEquals(1, bombs1.size());

        board.tact();
        board.tact();
        board.tact();
        board.tact();

        List<Bomb> bombs2 = board.getBombs();
        assertEquals(0, bombs2.size());

        assertEquals(0, bombs1.size());
    }
А вот и реализация
    public List<Bomb> getBombs() {
        return ListUtils.getUnmodifiableList(new ListUtils.ListFactory() {
            @Override
            public List create() {
                List<Bomb> result = new LinkedList<Bomb>();
                for (Bomb bomb : getSuperBombs()) {
                    result.add(new BombCopier(bomb));
                }
                return result;
            }
        });
    }
При этом пришлось откопать свои старые залежи и немного порефлексировать с ними, расширив ProxyFactory, который я давным давно писал. В результате теперь я имею возможность делать так
public class ListUtils {

    public interface ListFactory {
        Object create();
    }

    public static List<Bomb> getUnmodifiableList(final ListFactory factory) {
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = factory.create();
                Object invoke = method(method.getName()).withParameterTypes(method.getParameterTypes()).in(result).invoke(args);
                return ProxyFactory.resultBuilder().dontCallRealMethod().returns(invoke).get();
            }
        };
        return ProxyFactory.object(factory.create()).spy(handler).getAs(List.class);
    }
}
Короче поигрался в свое удовольствие. Старая версия описана тут, а новую версию ProxyFactory можно скачать отсюда (а вот и репозиторий).

Суть нового функционала в том, что я могу взять любой объект и встроить в него шпиона, который будет делать полезные для меня действия. AOP только без спринга. Напомню критикам, что я всего лишь играюсь в код... Не воспринимайте это серьензо.
    interface Some {
        String method(String input);
    }

    class SomeImpl implements Some {
        public String method(String input) {
            return "SomeImpl say: " + input;
        }

        public String method2(String input) {
            return "SomeImpl say from another method: " + input;
        }
    }

    @Test
    public void shouldCanUseAfterRealMethod() throws Throwable {
        final ProxyFactory.After after = new ProxyFactory.After() {
            public Object doit(Object result) {
                return result + "_zxc";
            }
        };

        InvocationHandler before = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return ProxyFactory.resultBuilder().with("asd_" + args[0]).doAfter(after).get();
            }
        };

        Some impl2 = ProxyFactory.object(impl).spy(before).getAs(Some.class);

        assertEquals("SomeImpl say: asd_qwe_zxc", impl2.method("qwe"));
    }
Тут ProxyFactory.resultBuilder() можно использоваться несколькими способами.
ProxyFactory.resultBuilder().with("new args").returns("new answer").get()
сразу после handler будет вызван исходный метод объекта но с новым аргументом "new args", а после его выполнения результат подменится на "new answer".
ProxyFactory.resultBuilder().get()
Ничего не изменился - сразу после отработки handler будет вызван исходный метод с исходными артументами, а его результат вернется клиенту.
ProxyFactory.resultBuilder().call("method2").with("new args").get()
Сразу после handler будет вызван другой (method2) метод объекта, за которыми шпионим, с другими аргмуентами "new args", а результат выполнения уйдет клиенту.
ProxyFactory.resultBuilder().call("method2").get()
Сразу после handler будет вызван другой (method2) метод объекта, за которыми шпионим, с другими исходными аргументами, а результат выполнения уйдет клиенту.
ProxyFactory.resultBuilder().returns("new answer").get()
Ничего не трогаем, переопределяем только результат "new answer"
ProxyFactory.resultBuilder().dontCallRealMethod().returns("new answer").get()
Говорим, чтобы выполнялся только handler и клиенту подсунем новый результат "new answer"
ProxyFactory.resultBuilder().after(new ProxyFactory.After() {
        public Object doit(Object result) {
            return result; // do smth
        }
    }).get() 
Говорим, что после выполнения исходного метода надо вызвать наш Answer.doit()
Как-то так.

Может кому пригодится...

Бомбермен: Любопытная бага с лиснерами

В процессе разработки Bombrman для Coding Dojo я сталкивался с рядом любопытных моментов. Например.
Каждый такт игры я итерируюсь по всем бомбам чтобы уведомить их таймеры ...
    private void tactAllBombs() {
        for (Bomb bomb : bombs) {
            bomb.tick();
        }
    }
...а в bomb.tick() я отсчитываю такты самой бомбы - когда-то же она должна взорваться...
    public void tick() {
        timer--;
        if (timer == 0) {
            boom();
        }
    }
...и если таймер истек, то бомба бабахает!
    private void boom() {
        if (affect != null) {
            affect.boom(this);
        }
    }
affect - это слушатель, подписанный на "бабах" бомбы. В данном конкретном случае у меня это анонимный класс на борде. То есть борда прописывается на взрыв бомбы и делает беспорядок среди попавших под раздачу. Подписывается она в момент когда кто-то бомбермен дропает бомбу.
    public void drop(Bomb bomb) {
            bomb.setAffect(new Boom() {
                @Override
                public void boom(Bomb bomb) {
                    bombs.remove(bomb);
                    killAllNear();
                }
            });
            bombs.add(bomb);
        }
    }
И вот тут самое интересное - я в этом лиснере уничтожаю бобму из списка оставленных на карте. Но тут конфликт. На самом верхнем уровне я итерируюсь по бомбам, а потом в самой глубине я удаляю из итерируемого списка - это приводит к тому, что последняя бомба не тикает, если перед ней взорвалась предыдущая.
Лечится так.
    private void tactAllBombs() {
        for (Bomb bomb : bombs.toArray(new Bomb[0])) {
            bomb.tick();
        }
    }

вторник, 5 марта 2013 г.