<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-5342535388237643243</atom:id><lastBuildDate>Sat, 05 Oct 2024 02:04:28 +0000</lastBuildDate><category>C#</category><category>разработка ПО</category><category>юмор</category><category>Разное</category><category>Tools</category><category>.net</category><category>tdd</category><category>php</category><category>Библиотека</category><category>мысли в слух</category><category>javascript</category><category>ms sql ce</category><category>testing</category><category>visual studio</category><category>IoC</category><category>android</category><category>SublimeText 2</category><category>tddigest</category><category>unit testing</category><category>задачки</category><category>переводы</category><category>рефакторинг</category><category>.net framework</category><category>IE</category><category>Silverlight</category><category>html</category><category>jquery</category><category>sqlite</category><category>bdd</category><category>coffeescript</category><category>java</category><category>linq</category><category>phpunit</category><category>sql</category><category>unity</category><category>xunit</category><category>отдых</category><category>подкасты для разработчика</category><category>IE8</category><category>ORM</category><category>RegExpr</category><category>ZenCoding</category><category>atdd</category><category>knockout.js</category><category>moq</category><category>msswit2013</category><category>mysql</category><category>play market</category><category>samsung apps</category><category>soap</category><category>usability</category><category>web services</category><category>монетизация</category><category>приложение</category><category>ссылки</category><category>256</category><category>AMD</category><category>Access</category><category>Custom splash screen</category><category>DDD</category><category>DI</category><category>NetBeans</category><category>Shortcut</category><category>SpicIE</category><category>Super Mario</category><category>Windows 7</category><category>admin2012.ru</category><category>admob</category><category>android conventions</category><category>android studio</category><category>angular.js</category><category>ant</category><category>antipattern</category><category>autocomplete</category><category>backbone.js</category><category>background repeat</category><category>batch file</category><category>batman.js</category><category>bootstrap</category><category>bug</category><category>build</category><category>clojurescript</category><category>codeigniter</category><category>coding style</category><category>components</category><category>css</category><category>eclipse</category><category>facebook</category><category>gradle</category><category>hot keys</category><category>ide</category><category>ion auth</category><category>jasmine</category><category>javas</category><category>jquery ui</category><category>justify</category><category>localDB</category><category>massive</category><category>micro orm</category><category>mocha</category><category>mock</category><category>mono</category><category>monodroid</category><category>mpress</category><category>mvc framework</category><category>nodejs</category><category>nosql</category><category>npm</category><category>object db</category><category>opera apps</category><category>phonegap</category><category>qunit</category><category>require.js</category><category>screenshoot</category><category>sdk</category><category>singleton</category><category>slide me</category><category>social network</category><category>spellcheck</category><category>style</category><category>svn</category><category>text align</category><category>torrents.ru</category><category>tortoisesvn</category><category>twitter</category><category>uml</category><category>virus</category><category>Оптимизация сайта</category><category>Ошибка 720</category><category>армагедон</category><category>видео</category><category>вконтакте</category><category>декомпилятор</category><category>итоги</category><category>кодировка</category><category>космос</category><category>маркет</category><category>обфускация</category><category>прибыль</category><category>скачивания</category><category>статистика</category><title>Холодильник - тоже космос...</title><description>Thinking out loud about development and etc.</description><link>http://sly-and-fluffy.blogspot.com/</link><managingEditor>noreply@blogger.com (Anonymous)</managingEditor><generator>Blogger</generator><openSearch:totalResults>192</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-4850591023923515015</guid><pubDate>Fri, 14 Feb 2014 17:59:00 +0000</pubDate><atom:updated>2014-02-14T19:59:44.111+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">admob</category><category domain="http://www.blogger.com/atom/ns#">android</category><category domain="http://www.blogger.com/atom/ns#">samsung apps</category><category domain="http://www.blogger.com/atom/ns#">итоги</category><category domain="http://www.blogger.com/atom/ns#">космос</category><category domain="http://www.blogger.com/atom/ns#">маркет</category><category domain="http://www.blogger.com/atom/ns#">монетизация</category><category domain="http://www.blogger.com/atom/ns#">прибыль</category><category domain="http://www.blogger.com/atom/ns#">скачивания</category><category domain="http://www.blogger.com/atom/ns#">статистика</category><title>Android-приложение: первые итоги. </title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Два месяца прошло с момента публикации &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.onestepapp.facts.thailand.phones&quot; target=&quot;_blank&quot;&gt;моего первого Android&lt;/a&gt; приложения на Play market, &lt;a href=&quot;http://life-thai.com/&quot; target=&quot;_blank&quot;&gt;я перебралась на Самуи&lt;/a&gt;, а гугл по-тихоньку начал &lt;a href=&quot;http://habrahabr.ru/post/211224/&quot; target=&quot;_blank&quot;&gt;зачищать маркет&lt;/a&gt; от приложений с альтернативными способами оплаты, в то время, как Таиланд собрался отправить в космос первого своего человека. Время летит, и сегодня я опубликовала &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.onestepapp.facts.vietnam&quot; target=&quot;_blank&quot;&gt;следующее приложение&lt;/a&gt;, но об этом в другой раз. Посмотрим, что у нас со средней температурой по больнице. &lt;/div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Итак, небольшая сводка статистики из магазинов, &lt;a href=&quot;http://sly-and-fluffy.blogspot.com/2014/01/blog-post.html&quot; target=&quot;_blank&quot;&gt;на которых&lt;/a&gt; было выложено приложение. Напомню параметры &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.onestepapp.facts.thailand.phones&quot; target=&quot;_blank&quot;&gt;приложения&lt;/a&gt;: бесплатное (с рекламой), переведено на три языка (ру, en, de). &lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;b&gt;Google Play&lt;/b&gt; - 244 скачивания (16.12.2013 - 14.02.2014) совсем не густо, но и не пусто :) Хотя я рассчитывала на большее, но стоит учитывать специфику приложения и смотреть на мир реалистично.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;b&gt;Samsung market&lt;/b&gt; - 146 скачиваний (22.01.2014 - 14.02.2104) Превзошёл все мои ожидания. Наверное, самый неудобный, самый тяжелый, самый придирчивый маркет, но какая отдача!&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;b&gt;Amazon market&lt;/b&gt; - целых 12 (!) скачиваний (период 16 января - 14 февраля), хотя я ожидала от этого маркета гораздо больше.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;b&gt;Opera market&lt;/b&gt; -&amp;nbsp; 5 скачиваний (10/01/2014 - 14/02/2014), no comments. &lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Добавлю некоторые комментарии. Если смотреть статистику по языкам на Google Play, то превалирует русскоязычный сегмент. На Samsung market и Amazon market приложение загружалось с английским переводом. Если наложить цифры загрузок приложения, дату аппрува приложения на Samsung maket на статистику от admob, то явный прирост прибыли начинается с появления приложения в Samsung market.&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigasR6Y2hKXsyrF0h3NFhvFL8F2XeJl8aEXPVHIatsFghZe2gM2gitWRMKLSXI3dsSmEPy6IqIAkzXM92Ogn4Ouxpfi-xz84E2Pegw8g4WO2S-oyGssvT6RRYA65vtm4Q5DHG9FMtUQvQ/s1600/stat.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigasR6Y2hKXsyrF0h3NFhvFL8F2XeJl8aEXPVHIatsFghZe2gM2gitWRMKLSXI3dsSmEPy6IqIAkzXM92Ogn4Ouxpfi-xz84E2Pegw8g4WO2S-oyGssvT6RRYA65vtm4Q5DHG9FMtUQvQ/s1600/stat.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Кроме того, весь доход идёт с англоязычного сегмента. Выводы очевидны.&lt;/div&gt;
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2014/02/android.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigasR6Y2hKXsyrF0h3NFhvFL8F2XeJl8aEXPVHIatsFghZe2gM2gitWRMKLSXI3dsSmEPy6IqIAkzXM92Ogn4Ouxpfi-xz84E2Pegw8g4WO2S-oyGssvT6RRYA65vtm4Q5DHG9FMtUQvQ/s72-c/stat.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-8899883713328950143</guid><pubDate>Thu, 23 Jan 2014 04:03:00 +0000</pubDate><atom:updated>2014-02-14T20:06:19.217+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">android</category><category domain="http://www.blogger.com/atom/ns#">opera apps</category><category domain="http://www.blogger.com/atom/ns#">play market</category><category domain="http://www.blogger.com/atom/ns#">samsung apps</category><category domain="http://www.blogger.com/atom/ns#">slide me</category><category domain="http://www.blogger.com/atom/ns#">приложение</category><title>Первое андроид-приложение: публикация</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIr0OU5z5DQamce6KbHSxrAVLggBItM_NLjzFAZWoWvQ6oYhooevK0M4SxRkJJAaHHAX15hqvz8MUCRFBDeylfXP0sF0ih3MYtrNUS-bs__caUTOWXuiv1hT1oquPrVMaeMdhtTCtPoo8/s1600/googleplay.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIr0OU5z5DQamce6KbHSxrAVLggBItM_NLjzFAZWoWvQ6oYhooevK0M4SxRkJJAaHHAX15hqvz8MUCRFBDeylfXP0sF0ih3MYtrNUS-bs__caUTOWXuiv1hT1oquPrVMaeMdhtTCtPoo8/s1600/googleplay.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Продолжаю серию постов о своём первом андроид-приложении. Сегодня мысли о публикации приложения в разных маркетах. &lt;/div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;
И так, настал этот долгожданный момент - приложение написано, оттестировано и готово к публикации!&lt;/div&gt;
&lt;br /&gt;
&lt;a href=&quot;http://play.google.com/&quot; target=&quot;_blank&quot;&gt;Play Market&lt;/a&gt; - место #1, куда должно быть загружено приложение. &lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Самый большой магазин == большая конкуренция + особенность Play market в виде большого количества трэша. Возникает очевидный вопрос:&amp;nbsp; насколько тяжело новому приложению пробиться через толпы бездумных клонов и показать себя миру? Для размышлений кучек интересной инфографики от &lt;a href=&quot;http://www.stardustspm.com/&quot; target=&quot;_blank&quot;&gt;Stardust&lt;/a&gt;, из которой видно, что пока, легче всего продвинуться в Winphone Marketplace: и приложений там немного, и в день публикуется всего 286 тогда, когда в Google Play приложения льются рекой по 1107 штук в день. А, может, действительно, зачем этот андроид? :)&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgEjs6GkS_B401kKPKV6XgXWGdB-hz6rPLSTES86EP5wFvoBgZ5od6SNv9jO4CRj-JLlmNz0wm9WBmo7rkIOQ_8Bcwvtt9YyqZvXQf6OXWgb32ytTtf_aNSZ0USf_j5T1jUQFF5ambbEs/s1600/Capture.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgEjs6GkS_B401kKPKV6XgXWGdB-hz6rPLSTES86EP5wFvoBgZ5od6SNv9jO4CRj-JLlmNz0wm9WBmo7rkIOQ_8Bcwvtt9YyqZvXQf6OXWgb32ytTtf_aNSZ0USf_j5T1jUQFF5ambbEs/s1600/Capture.PNG&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Ладно, сопли в сторону, всем нелегко :)&lt;br /&gt;
Перво-наперво, идём на &lt;a href=&quot;http://developer.android.com/distribute/googleplay/publish/index.html&quot;&gt;http://developer.android.com/distribute/googleplay/publish/index.html&lt;/a&gt; и проверяем по пунктам своё приложение. Всё ли хорошо, ничего ли не упущено? Если да, теперь можно публиковать приложение в Play Market. Для этого нужно зарегистрироваться на Google Play Market как разработчику, процедура это не сложная, стоит 25$. Модерация приложения проходит быстро (около 4 часов).&lt;br /&gt;
Ссылка на приложение в &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.onestepapp.facts.thailand.phones&quot; target=&quot;_blank&quot;&gt;Google Play &lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;a href=&quot;http://samsungapps.com/&quot; target=&quot;_blank&quot;&gt;Samsung Apps&lt;/a&gt;&lt;br /&gt;
Регистрация бесплатная.&amp;nbsp; &lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Утомляет бесконечное заполнением форм. Как по мне, слишком много телодвижений для публикации приложения. Удивил тем, что скриншоты приложения должны быть строго определённого размера (800х480), 854х480 уже не прокатило, и 800х390 тоже не прокатило. &lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd6-EAvNic7OfD9eM9L3ip8GCV9khISbO0bxNXRMoHsnGI8QcyuNyf3UcEoarkt9IDr_XUZABw2WYw8n0NKkYidRB6z_vwr2UQMnUlJYWvVMeaTedh5gj-JV-B3Tf5hV6ve_frRNqpsLY/s1600/samsungmarket.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd6-EAvNic7OfD9eM9L3ip8GCV9khISbO0bxNXRMoHsnGI8QcyuNyf3UcEoarkt9IDr_XUZABw2WYw8n0NKkYidRB6z_vwr2UQMnUlJYWvVMeaTedh5gj-JV-B3Tf5hV6ve_frRNqpsLY/s640/samsungmarket.PNG&quot; height=&quot;337&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Дотошная модерация. Проверяли 4 дня и в итоге отклонили приложение, потому что оно содержало ссылку на сторонний маркет. В отчёте прикрепили скриншот и подробное описание проблемы:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8rctAbCpToGU011_T9BFhyRu2N0zuf_7flv2JScyYlHYt4BzBH4ba5Oic3TnVH_Y7dYPOMeibUiPGDUby5rDiSQbjcZBGECXJ0QxNWYEKnKmUUHmsCLsXVauECN0OFFgOI27rAkUcmK0/s1600/Screenshot_2014-01-14-11-46-43%5B1%5D%5B1%5D.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8rctAbCpToGU011_T9BFhyRu2N0zuf_7flv2JScyYlHYt4BzBH4ba5Oic3TnVH_Y7dYPOMeibUiPGDUby5rDiSQbjcZBGECXJ0QxNWYEKnKmUUHmsCLsXVauECN0OFFgOI27rAkUcmK0/s400/Screenshot_2014-01-14-11-46-43%5B1%5D%5B1%5D.png&quot; height=&quot;225&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;Defect&amp;gt;Application has a link to other application store - Google play. &lt;/span&gt;&lt;/div&gt;
Да, бывают в жизни и такие оплошности.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://developer.amazon.com/public/&quot; target=&quot;_blank&quot;&gt;Amazon&amp;nbsp;&lt;/a&gt;&lt;br /&gt;
Регистрация бесплатная. Тоже пришлось заполнять простыни, но по ощущениям приятнее, чем Samsung market.Специфика маркета - ориентированность на рынок США, поэтому, если приложение имеет локализацию, то вэлкам :)&lt;br /&gt;
Проверку приложение прошло довольно быстро, без каких-либо проблем. &lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://apps.opera.com/&quot; target=&quot;_blank&quot;&gt;Opera Apps&lt;/a&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Регистрация в 1 клик, бесплатная, что очень порадовало после Samsung Apps. Подтверждение моего аккаунта заняло два с половиной дня, после чего загруженные приложения стали доступны для скачивания.&lt;br /&gt;
Плюсы публикации приложения в этом магазине в том, что приложение автоматически попадает в Яндекс.Store и GetUpps! от Мегафона.&lt;br /&gt;
Ещё один плюс - удобная панель разработчика.&lt;br /&gt;
Из минусов - не понятно, сколько android-пользователей знают об этом магазине и каков размер аудитории. &lt;br /&gt;
Зато ссылку на приложение можно получить в виде такого красивого бейджа :)&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://apps.opera.com/badge.php?a=c&amp;amp;v=dark_v2&amp;amp;did=89965&amp;amp;pid=412253&quot; target=&quot;_blank&quot;&gt;&lt;img alt=&quot;Opera Mobile Store&quot; height=&quot;55&quot; src=&quot;https://apps.opera.com/badge.php?a=s&amp;amp;v=dark_v2&amp;amp;did=89965&amp;amp;pid=412253&quot; title=&quot;Opera Mobile Store&quot; width=&quot;173&quot; /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;br /&gt;
&lt;a href=&quot;http://slideme.org/&quot; target=&quot;_blank&quot;&gt;SlideMe&lt;/a&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Простая бесплатная регистрация. Приложение проверяли почти 3 дня и в итоге не приняли, поставив статус Forbidden c пояснением:&lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
AGGREGATED CONTENT (TEXT): Applications that are simply 
collections of text (quotes, tips, facts, jokes, SMS, news etc.) or 
other aggregated content are no longer being accepted on SlideME.
&lt;/blockquote&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
И обидно, и ведь не поспоришь: факты о Таиланде с авторскими фото попадают под одну из перечисленных категорий.&lt;/div&gt;
&lt;br /&gt;
&lt;a href=&quot;http://developer.getjar.mobi/&quot; target=&quot;_blank&quot;&gt;GetJar&lt;/a&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Маркет, о котором мне попадалось много хороших отзывов, но на котором так и не удалось зарегистрироваться - confirmation email от них так и не пришёл, хоть и обещали выслать :(&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Итак, зачем всё это? Ведь после регистрации в стольких маркетах, выкат обновлений становится трудоёмкой задачей. Думаю, ответ очевиден: если вы разработчик-одиночка и у вас нет денег на пиар и раскрутку приложения, то присутствие в нескольких маркетах сразу само по себе увеличит шансы на успех. К тому же, в моём случае монетизации через показ рекламы, чем больше скачиваний -&amp;gt; пользователей, тем больше шансов увеличить revenue.&lt;br /&gt;
&lt;b&gt;UPD.&lt;/b&gt; У Play market тоже, оказывается, есть badge-генератор &lt;a href=&quot;http://developer.android.com/distribute/googleplay/promote/badges.html&quot; target=&quot;_blank&quot;&gt;тут&lt;/a&gt;, только он не умеет генерировать бэйджи для русскоязычных приложений. Хм.&lt;/div&gt;
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2014/01/blog-post.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIr0OU5z5DQamce6KbHSxrAVLggBItM_NLjzFAZWoWvQ6oYhooevK0M4SxRkJJAaHHAX15hqvz8MUCRFBDeylfXP0sF0ih3MYtrNUS-bs__caUTOWXuiv1hT1oquPrVMaeMdhtTCtPoo8/s72-c/googleplay.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-5372753893775843345</guid><pubDate>Fri, 10 Jan 2014 13:00:00 +0000</pubDate><atom:updated>2014-01-23T06:04:44.270+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">android</category><category domain="http://www.blogger.com/atom/ns#">play market</category><category domain="http://www.blogger.com/atom/ns#">монетизация</category><category domain="http://www.blogger.com/atom/ns#">приложение</category><title>Первое android-приложение: мысли о монетизации</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Продолжаю серию заметок о разработке первого android-приложения. На этот раз речь о выборе стратегии монетизации приложения.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4 style=&quot;text-align: left;&quot;&gt;
Монетизация android-приложения&lt;/h4&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Монетизировать приложение можно по-разному. Выбор стратегии монетизации зависит от типа приложения. Можно продавать, можно показывать рекламу, можно встроить in-app продажи (например, скины, оружие, уровни и тд). Наиболее популярная модель монетизации на сегодняшний день - freemium, но такая модель подходит больше всего для игр. К слову, 80% доходов всего android-маркета приходится на долю игр. Опытные люди говорят, что в андроид-маркете больше можно заработать на рекламе/in-app продажах, чем на прямых продажах приложения.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://www.gorillabrand.org/files/6313/7207/8228/App.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://www.gorillabrand.org/files/6313/7207/8228/App.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Изначально моя стратегия была проста: сделать две версии - бесплатную с рекламой и платную за 1$, и радоваться жизни. Но не тут-то было. Граждане Украины не могут продавать приложения в android-маркете. Увы. Конечно, есть разные выходы из ситуации, но они либо не вполне легальны, либо сложны, запутаны и нелегальны в итоге. В интернетах можно нагуглить статьи на эту тему. А для граждан России полезная заметка с хабра &lt;a href=&quot;http://habrahabr.ru/post/191280/&quot; target=&quot;_blank&quot;&gt;&quot;Google Play -&amp;nbsp; работаем легально&quot;&lt;/a&gt;.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Тогда было решено монетизироваться только за счёт рекламы. Были рассмотрены разные варианты от разных рекламных сетей: и полноэкранная реклама, и обычные баннеры. Но из-за особенностей контента приложения и предполагаемой аудитории был выбран AdMob. Какие параметры важны при выборе рекламодателя: конечно же, цена за клик, ориентация на разные типы приложений (часто реклама только для игр) и покрытие аудитории (например, не все могут похвастаться наличием рекламы под русскоязычный сегмент android-маркета, и это проблема). Оплата кликов по рекламе колеблется в зависимости от страны. На примере AdMob, в США клик стоит где-то 0,7$ – 0,11$, а в Европе (Россия) в среднем около 0,03$. Вообщем, рассчитывать на золотые горы не стоит :) На хабре есть отличная статья, где подробно рассмотрены рекламные сети с примерами дохода от них. Называется &quot;&lt;a href=&quot;http://habrahabr.ru/post/192570/&quot; target=&quot;_blank&quot;&gt;Не AdMob-ом единым. Обзор интересных рекламных сетей и не только&lt;/a&gt;&quot;. И интересный (цифрами) пример увеличения прибыли после добавления полноэкранной рекламы в игру &quot;&lt;a href=&quot;http://habra-cache.ru/post/201464/&quot; target=&quot;_blank&quot;&gt;Польза от полноэкранной рекламы&lt;/a&gt;&quot;.&lt;br /&gt;
У AdMob есть хороший (как мне показалось) &lt;a href=&quot;https://developers.google.com/mobile-ads-sdk/&quot; target=&quot;_blank&quot;&gt;SDK&lt;/a&gt;, подключить и настроить рекламу в приложении труда не составило.&lt;/div&gt;
Пока цифр о заработке на AdMob показать никаких не могу, но как насобирается статистика (пусть даже плачевная) сразу напишу.&amp;nbsp; &lt;br /&gt;
Часть 1: &lt;a href=&quot;http://sly-and-fluffy.blogspot.com/2013/12/android.html&quot; target=&quot;_blank&quot;&gt;Простое, но странное в Android&lt;/a&gt;&lt;br /&gt;
Част 2: &lt;a href=&quot;http://sly-and-fluffy.blogspot.com/2013/12/android-studio-gradle.html&quot; target=&quot;_blank&quot;&gt;Android Studio, Gradle, соц. сети&lt;/a&gt;&lt;br /&gt;
Часть 3: Мысли о монетизации&lt;br /&gt;
Часть 4: &lt;a href=&quot;http://sly-and-fluffy.blogspot.com/2014/01/blog-post.html&quot; target=&quot;_blank&quot;&gt;Публикация&lt;/a&gt; &lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2014/01/android.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-3883474190675965193</guid><pubDate>Fri, 20 Dec 2013 17:05:00 +0000</pubDate><atom:updated>2014-01-23T05:41:33.122+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">android</category><category domain="http://www.blogger.com/atom/ns#">android conventions</category><category domain="http://www.blogger.com/atom/ns#">android studio</category><category domain="http://www.blogger.com/atom/ns#">build</category><category domain="http://www.blogger.com/atom/ns#">coding style</category><category domain="http://www.blogger.com/atom/ns#">facebook</category><category domain="http://www.blogger.com/atom/ns#">gradle</category><category domain="http://www.blogger.com/atom/ns#">hot keys</category><category domain="http://www.blogger.com/atom/ns#">ide</category><category domain="http://www.blogger.com/atom/ns#">sdk</category><category domain="http://www.blogger.com/atom/ns#">social network</category><category domain="http://www.blogger.com/atom/ns#">twitter</category><category domain="http://www.blogger.com/atom/ns#">вконтакте</category><title>Android Studio, Gradle, соц. сети</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Продолжаю тему полевых заметок, начатую в &lt;a href=&quot;http://sly-and-fluffy.blogspot.com/2013/12/android.html&quot; target=&quot;_blank&quot;&gt;предыдущем посте&lt;/a&gt;. В этот раз немного об инструментах и чуть-чуть о социальщине.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;1. Android Studio&lt;/b&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Если честно, это не первый мой опыт написания приложения под Android. До этого я написала несколько простеньких приложений, используя Eclipse, но до логического завершения ни одно из них не дошло. В этот раз я решила, что всё серьезно. Поставила Android Studio. И.. дааа... Как по мне, Android Studio - ещё необкатанный продукт. Много неудобных вещей. Много вещей, которые вызывают недоумение. Может, это дело привычки - привыкла я к комфортной Visual Studio, которая работает быстро, чётко и предсказуемо. Но сравнивать эти два продукта глупо, ведь Android Studio распространяется бесплатно.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Заметка 1. Если вдруг ваша Android Studio перестанет видеть установленный JDK (предполагается, что JAVA_HOME настроен корректно), а проект компилится нормально, то всё, что нужно сделать, это File-&amp;gt;Invalidate caches / Restart&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Заметка 2. Если вдруг Android Studio сказала, что произошла Internal error (ненавязчивое красное всплывающее сообщение в верхнем правом углу), то лучше сразу перезапустить IDE. Мне бы это сэкономило много времени :(&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Полезные ссылки: &lt;a href=&quot;http://developer.android.com/sdk/installing/studio-tips.html&quot; target=&quot;_blank&quot;&gt;Android Studio Tips &amp;amp; Tricks&lt;/a&gt;, а тут полный &lt;a href=&quot;http://www.jetbrains.com/idea/documentation/index.jsp&quot; target=&quot;_blank&quot;&gt;список hot keys&lt;/a&gt;&lt;br /&gt;
И ещё одна полезная ссылка&amp;nbsp;&lt;a href=&quot;http://www.slideshare.net/martyhall/android-tutorial-coding-style-the-official-android-conventions&quot; target=&quot;_blank&quot;&gt;&quot;Coding Style - The Official Android Conventions&quot;&lt;/a&gt; на slideshare.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;
&lt;b&gt;2. Gradle&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Градл - это мощь. Это новая билд-система для Android Studio. Круто. Что ещё сказать. Один раз наконфигурячишь, а потом радуешься. Легко билдить под разные девайсы.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Для знакомства с градл рекомендую посмотреть видео с Google I/O 2013 &lt;a href=&quot;http://www.youtube.com/watch?v=LCJAgPkpmR0&quot; target=&quot;_blank&quot;&gt;&quot;The New Android SDK Build System&quot;&lt;/a&gt;&lt;br /&gt;
&lt;i&gt;Заметка 3. Если вдруг градл как-то странно работает, убедитесь, что в Android Studio не произошла internal error. Решается всё перезапуском студии.&amp;nbsp;&amp;nbsp;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;Заметка 4. Градл обожает кэш. Поэтому, если вы добавили в проект библиотеку, а градл не может забилдить, то нужно почистить кэш (&quot;gradlew clean&quot; в консоли) и заодно проверить dependencies в&amp;nbsp;build.gradle. &lt;/i&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;
&lt;b&gt;3. Интеграция с социальными сетями&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Куда ж без этого в наше-то время? Фейсбук, конечно, порадовал: у них есть свой SDK, с помощью которого несложно интегрироваться социальную составляющую в своё приложение. &lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Ссылка на &lt;a href=&quot;https://developers.facebook.com/docs/android/&quot; target=&quot;_blank&quot;&gt;Facebook SDK for Android&lt;/a&gt;.&lt;br /&gt;
&lt;i&gt;Заметка 5. Если приложение, после интеграции с facebook SDK падает при запуске с исключением &lt;b&gt;com.facebook.c.f got an unexpected method signature&lt;/b&gt;, убедитесь, что в конфиг ProGuard добавлена строка &quot;&lt;b&gt;-keep class com.facebook.** {*;}&lt;/b&gt;&quot;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
C twitter тоже проблем нет. На официальной странице &lt;a href=&quot;https://dev.twitter.com/docs/twitter-libraries&quot; target=&quot;_blank&quot;&gt;Twitter Libraries&lt;/a&gt; есть ссылка на &lt;a href=&quot;http://twitter4j.org/&quot; target=&quot;_blank&quot;&gt;Twitter4J&lt;/a&gt;.&amp;nbsp; Кроме того, есть ещё библиотеки &lt;a href=&quot;http://sugree.com/project/twitter-android-sdk&quot; target=&quot;_blank&quot;&gt;Sugree Twitter Android SDK&lt;/a&gt; (плюс - наличие готового UI для авторизации пользователя, минус - небольшой функционал) и&amp;nbsp;
&lt;a href=&quot;http://www.winterwell.com/software/jtwitter.php&quot; target=&quot;_blank&quot;&gt;    JTwitter&lt;/a&gt;(без UI,&amp;nbsp; функционал похож на twitter4j).&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
А вот Вконтакте... ну, в отсутствии официального SDK парни &lt;a href=&quot;https://github.com/thest1/Android-VKontakte-SDK&quot; target=&quot;_blank&quot;&gt;свой SDK&lt;/a&gt; пишут. Низкий им поклон :)&lt;br /&gt;
UPD: Ура, дождались! Вот и Вконтакте выпустили официальный SDK для Android! Лежит на github&#39;e: &lt;a href=&quot;https://github.com/VKCOM/vk-android-sdk&quot;&gt;https://github.com/VKCOM/vk-android-sdk&lt;/a&gt; &lt;br /&gt;
Продолжение &lt;a href=&quot;http://sly-and-fluffy.blogspot.com/2014/01/android.html&quot; target=&quot;_blank&quot;&gt;о монетизации приложения&lt;/a&gt;.&amp;nbsp; &lt;/div&gt;
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/12/android-studio-gradle.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-5655734839194548463</guid><pubDate>Sun, 15 Dec 2013 07:51:00 +0000</pubDate><atom:updated>2014-01-10T15:39:43.610+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">android</category><category domain="http://www.blogger.com/atom/ns#">background repeat</category><category domain="http://www.blogger.com/atom/ns#">justify</category><category domain="http://www.blogger.com/atom/ns#">spellcheck</category><category domain="http://www.blogger.com/atom/ns#">text align</category><title>Простое, но странное в Android</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Вот и дошли руки написать приложение под Android. В процессе, конечно же, без приключений не обошлось. И так, простые, но странные вещи, с которыми мне пришлось столкнуться, разрабатывая простое приложение под Android.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&amp;nbsp;&lt;b&gt;1. Как выровнять текст по ширине (justify) в Android? &lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Никак. Можно отцентрировать, выровнять текст по правому краю или по левому. Народ предлагает использовать WebView, и там уже с помощью css-стилей задавать выравнивание. Получается такое уже громоздкое решение:&lt;/div&gt;
&lt;b&gt;Код&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&amp;nbsp;&lt;/b&gt; &lt;br /&gt;
&lt;code class=&quot;prettyprint&quot;&gt;
WebView view = findViewById(R.id.web_view);&lt;br /&gt;
view.loadData(getString(R.string.hello), &quot;text/html&quot;, &quot;utf-8&quot;);&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettyprint&quot;&gt;&lt;br /&gt;
&lt;/code&gt;
&lt;b&gt;Ресурсы&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&amp;nbsp;&lt;/b&gt; &lt;br /&gt;
&lt;code class=&quot;prettyprint&quot;&gt;
&amp;lt;string name=&quot;hello&quot;&amp;gt;&lt;br /&gt;
&amp;lt;![CDATA[&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
 &amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
 &amp;lt;body style=&quot;text-align:justify;color:gray;background-color:black;&quot;&amp;gt;&lt;br /&gt;
  Я строка, я ничего не хочу делать. Я хочу быть выровненой по ширине.&lt;br /&gt;
 &amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
]]&amp;gt;&lt;br /&gt;
&amp;lt;/string&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettyprint&quot;&gt;
&lt;/code&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Есть уже готовые решения (например, &lt;a href=&quot;https://github.com/bluejamesbond/TextJustify-Android&quot; target=&quot;_blank&quot;&gt;это&lt;/a&gt;), чтобы не писать всё ручками.&lt;br /&gt;
Но, если вам нужно использовать нестандартный шрифт, то этот вариант принесёт много дополнительных проблем: текст сразу лучше сохранять в виде html-страницы, в стилях которой задавать нужный шрифт (ага, и шрифт лучше бы лежал бы в той же папке, где и страница) и остальное позиционирование. Много телодвижений. Очень.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Есть ещё вариант выравнять текст без использования WebView (к сожалению, ссылка где-то потерялась), но сразу минусы: нужно ручками подбирать подходящий коэффициент для правильного выравнивания (ага, разные экраны у разных устройств) и , как бонус, жуткие тормоза.&lt;br /&gt;
В Winforms, кстати, такая же проблема с выравниванием текста, так что это только кажется странным после веба, где всё легко делается с помощью стилей. &lt;/div&gt;
&lt;b&gt;2. Где можно задать метод наложения фона у layout?&lt;/b&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Нигде. По умолчанию фон растягивается. Можно использовать такой хак: делаем лэйаут с фоном, а потом используем этот лэйаут как фон, его можно повторять.&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;repeat.xml&lt;/b&gt;&lt;br /&gt;
&lt;code class=&quot;prettyprint&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt;&lt;br /&gt;
&amp;lt;bitmap xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&lt;br /&gt;
    android:src=&quot;@drawable/bg&quot;&lt;br /&gt;
    android:tileMode=&quot;repeat&quot; /&amp;gt;&lt;br /&gt;
&lt;/code&gt;
&lt;b&gt;&amp;nbsp;&lt;/b&gt; &lt;br /&gt;
&lt;b&gt;someactivity.xml&lt;/b&gt;&lt;br /&gt;
&lt;code class=&quot;prettyprint&quot;&gt;
 &amp;lt;TableLayout&lt;br /&gt;
        android:layout_width=&quot;fill_parent&quot;&lt;br /&gt;
        android:layout_height=&quot;fill_parent&quot;&lt;br /&gt;
        android:layoutMode=&quot;opticalBounds&quot;&lt;br /&gt;
        android:background=&quot;@layout/repeat&quot;&lt;br /&gt;
&amp;gt;&amp;lt;/TableLayout&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
&lt;/code&gt;
&lt;b&gt;3. Мой текст имеет красное подчёркивание. Что это и как это убрать?&lt;/b&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjSN_Kad0b0vuRtd6tGUnauXw7oVeH0MRpXmqkdozXkgQSEROqpcoWLpNa1F4LjOtHuaaElFE8XNenYkLL6ipEhAz9_3ip3tbyJnfz1kfHMdiyuImFHTrCzQu2B8Gyjl2YNeVrEViiBk4/s1600/Capture.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjSN_Kad0b0vuRtd6tGUnauXw7oVeH0MRpXmqkdozXkgQSEROqpcoWLpNa1F4LjOtHuaaElFE8XNenYkLL6ipEhAz9_3ip3tbyJnfz1kfHMdiyuImFHTrCzQu2B8Gyjl2YNeVrEViiBk4/s1600/Capture.PNG&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Это автопроверка текста на корректность (spell check) в Android. Убирается это легко: добавляем в TextView &lt;code class=&quot;prettyprint&quot;&gt;&lt;span class=&quot;pln&quot;&gt;android&lt;/span&gt;&lt;span class=&quot;pun&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;pln&quot;&gt;inputType&lt;/span&gt;&lt;span class=&quot;pun&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;str&quot;&gt;&quot;textNoSuggestions&quot; &lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;a href=&quot;http://sly-and-fluffy.blogspot.com/2013/12/android-studio-gradle.html&quot; target=&quot;_blank&quot;&gt;Вторая часть: интеграция с социальными сетями и Android Studio&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://sly-and-fluffy.blogspot.com/2014/01/android.html&quot; target=&quot;_blank&quot;&gt;Третья часть: про монетизацию&lt;/a&gt; &lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/12/android.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjSN_Kad0b0vuRtd6tGUnauXw7oVeH0MRpXmqkdozXkgQSEROqpcoWLpNa1F4LjOtHuaaElFE8XNenYkLL6ipEhAz9_3ip3tbyJnfz1kfHMdiyuImFHTrCzQu2B8Gyjl2YNeVrEViiBk4/s72-c/Capture.PNG" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-4700210028029564569</guid><pubDate>Wed, 16 Oct 2013 17:36:00 +0000</pubDate><atom:updated>2013-10-16T20:36:11.240+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">autocomplete</category><category domain="http://www.blogger.com/atom/ns#">bootstrap</category><category domain="http://www.blogger.com/atom/ns#">css</category><category domain="http://www.blogger.com/atom/ns#">jquery ui</category><category domain="http://www.blogger.com/atom/ns#">style</category><title>Bootstrap + jQuery UI Autocomplete</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Подключить jQuery UI Autocomplete к сайту на Bootstrap довольно просто, единственное - нужно немного допилить стили. Всем страждущим в помощь:&lt;/div&gt;
&lt;script src=&quot;https://gist.github.com/daz/2168334.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/10/bootstrap-jquery-ui-autocomplete.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-7279132636821334797</guid><pubDate>Mon, 16 Sep 2013 14:03:00 +0000</pubDate><atom:updated>2013-09-16T17:03:44.673+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">clojurescript</category><category domain="http://www.blogger.com/atom/ns#">видео</category><category domain="http://www.blogger.com/atom/ns#">юмор</category><title>Про ClojureSript, пыщ-пыщ и в продакшн</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Нарезка самых сочных моментов из выступления Александра Соловьёва на JavaScript Frameworks Day 2013. Доклад был про ClojureScript, полная версия - &lt;a href=&quot;http://www.youtube.com/watch?v=R4sTvHXkToQ&quot; target=&quot;_blank&quot;&gt;тут&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;480&quot; src=&quot;//www.youtube.com/embed/SyWFvn0I6m8&quot; width=&quot;640&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/09/clojuresript.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-2547056131969968098</guid><pubDate>Thu, 25 Jul 2013 15:45:00 +0000</pubDate><atom:updated>2013-07-25T18:45:11.487+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">android</category><category domain="http://www.blogger.com/atom/ns#">ant</category><category domain="http://www.blogger.com/atom/ns#">eclipse</category><category domain="http://www.blogger.com/atom/ns#">java</category><category domain="http://www.blogger.com/atom/ns#">nodejs</category><category domain="http://www.blogger.com/atom/ns#">npm</category><category domain="http://www.blogger.com/atom/ns#">phonegap</category><title>PhoneGap step by step: установка и настройка</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Небольшое руководство по установке и настройке PhoneGap на Windows-машине.&lt;br /&gt;
Возможные проблемы и способы решения в конце руководства.&amp;nbsp; &lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;
1. Подготовительный этап&lt;/h3&gt;
&amp;nbsp;1.1. &lt;a href=&quot;http://developer.android.com/sdk/index.html&quot; target=&quot;_blank&quot;&gt;Скачать&lt;/a&gt; и распаковать Android SDK (я распаковала в C:\dev)&lt;br /&gt;
&amp;nbsp;1.2. &lt;a href=&quot;http://www.oracle.com/technetwork/java/javase/downloads/index.html&quot; target=&quot;_blank&quot;&gt;Скачать&lt;/a&gt; и поставить JDK&lt;br /&gt;
&amp;nbsp;1.3. &lt;a href=&quot;http://ant.apache.org/bindownload.cgi&quot; target=&quot;_blank&quot;&gt;Скачать&lt;/a&gt; и распаковать Ant (я распаковала в D:\apache-ant)&lt;br /&gt;
&amp;nbsp;1.4. Добавить в системную переменную PATH путь к Android SDK, Java, Ant (;C:\dev\sdk\tools;C:\dev\sdk\platforms;C:\dev\sdk\platform-tools;C:\dev\sdk;%JAVA_HOME%\bin;D:\apache-ant\bin) &lt;br /&gt;
&amp;nbsp;1.5. В командной строке вызвать &lt;code class=&quot;prettycode&quot;&gt;android&lt;/code&gt; и посмотреть, что нужно обновить &lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDbPaTU3W856Z_VTi6y0Ohibdcjttb_Qq2td0vLv3q5-xxTGUbGv7ksD2yWbXjM2loUJrTvD0xxnC4EncUrVPqS6ZLSTLfKrqmtoQnFIgYVVFvM-IcJ3nejK0pqb60vNPJCoCFTG54nqI/s1600/Capture.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;473&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDbPaTU3W856Z_VTi6y0Ohibdcjttb_Qq2td0vLv3q5-xxTGUbGv7ksD2yWbXjM2loUJrTvD0xxnC4EncUrVPqS6ZLSTLfKrqmtoQnFIgYVVFvM-IcJ3nejK0pqb60vNPJCoCFTG54nqI/s640/Capture.PNG&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
2. Установка PhoneGap &lt;/h3&gt;
&amp;nbsp;2.1. &lt;a href=&quot;http://nodejs.org/download/&quot; target=&quot;_blank&quot;&gt;Скачать&lt;/a&gt; и поставить nodejs&lt;br /&gt;
&amp;nbsp;2.2. Проверяем системную переменную &lt;b&gt;PATH&lt;/b&gt; (должна содержать путь к npm&amp;nbsp; &lt;b&gt;%AppData%/npm&lt;/b&gt;&quot;, если нет - доабвляем )&lt;br /&gt;
&amp;nbsp;2.3. Устанавливаем PhoneGap: в командной строке выполняем:&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;npm install -g phonegap&lt;/code&gt;&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
3.Тестовый запуск&lt;/h3&gt;
&amp;nbsp;3.1. Создаём тестовое приложение:&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;phonegap create D:/projects/cardy --name &quot;My App&quot; --id &quot;ts.cardy&quot;&lt;/code&gt;&lt;br /&gt;
&amp;nbsp;3.2. Билдим
&lt;code class=&quot;prettyprint&quot;&gt;&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettyprint&quot;&gt;&amp;nbsp;cd D:/projects/cardy&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettyprint&quot;&gt;&amp;nbsp;phonegap local run android&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6RNL-QF9jw6SCqxrKO2Aszi32wQgeX3MQcreofKbuHK7CuyEyt_xk8kwlptr4uiuFlz24DMQF2qiv_L4cur4PDdHqFyVZzNS3hkqw7tSCkchA1L0hIhxalzUOHTrhqSoxg5AYy8UvToI/s1600/Capture2.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6RNL-QF9jw6SCqxrKO2Aszi32wQgeX3MQcreofKbuHK7CuyEyt_xk8kwlptr4uiuFlz24DMQF2qiv_L4cur4PDdHqFyVZzNS3hkqw7tSCkchA1L0hIhxalzUOHTrhqSoxg5AYy8UvToI/s1600/Capture2.PNG&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
3.3. Запускаем Eclipse, Ctrl+N и создаем новый Android project из существующего кода:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3fsT3QKHxmIs8mkavJTl61PYPL2eCBwAdqsMyAbFweY91FriXULFE1BZZ1UWKdafeqZ7koOnvnuLNIwb4STVLU3s0dpU5lyOUubtGKuHhaWoZw8IOTlE81nzn6AomwMElhf0qvOpdUdU/s1600/Capture3.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3fsT3QKHxmIs8mkavJTl61PYPL2eCBwAdqsMyAbFweY91FriXULFE1BZZ1UWKdafeqZ7koOnvnuLNIwb4STVLU3s0dpU5lyOUubtGKuHhaWoZw8IOTlE81nzn6AomwMElhf0qvOpdUdU/s1600/Capture3.PNG&quot; /&gt;&amp;nbsp;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Выбираем папку, в которой PhoneGap создал проект и клацаем Next.&amp;nbsp;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVriVVVfx37qBPPCNAQA_TMH6KWRYzeWlSdNKFwHNFV3pSgjBINF-Ot3ctcxMYzw_lnQZ9Xhv8lix4M55CKtK8GTybjCT0JAVvb2Rw5kG8RnKYRewcC9DQ3YVk6rRaWG2NiB7ijVu3mPM/s1600/Capture4.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVriVVVfx37qBPPCNAQA_TMH6KWRYzeWlSdNKFwHNFV3pSgjBINF-Ot3ctcxMYzw_lnQZ9Xhv8lix4M55CKtK8GTybjCT0JAVvb2Rw5kG8RnKYRewcC9DQ3YVk6rRaWG2NiB7ijVu3mPM/s1600/Capture4.PNG&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Эклипс добавил в список проектов наш тестовый проект.&lt;br /&gt;
Клацаем по нему правой кнопкой мыши, выбираем Run As -&amp;gt; Android Application и ждём запуска эмулятора:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwSvpcEwfkyi8AigsqL5WxPZD_YiD2m9D70AYYCHmxXN6PAA1oKaG7D8n1puPNByPRmO24TGxxkJG6J_PEz5P6EPAoxd1ffolODOK8FTfpgU2zsdzi8xiGG3vRjgjSScwpSYQcnwjfLzQ/s1600/capture5.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwSvpcEwfkyi8AigsqL5WxPZD_YiD2m9D70AYYCHmxXN6PAA1oKaG7D8n1puPNByPRmO24TGxxkJG6J_PEz5P6EPAoxd1ffolODOK8FTfpgU2zsdzi8xiGG3vRjgjSScwpSYQcnwjfLzQ/s1600/capture5.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Ура, всё работает!&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
4. Возможные сложности&lt;/h3&gt;
&lt;b&gt;Проблема:&lt;/b&gt; при запуске приложения ошибка&lt;br /&gt;
&lt;code class=&quot;prettyprint&quot;&gt; &amp;nbsp;Please install Android target 17 bla-bla-bla...&lt;/code&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVO5wEf1Sp2P-uPnnRL2Ar2Th-P8E5i7o8FqkaCDFgTjdHN9lh4eIxhp033IzzY4R4jjB0-bBEtsAYTxPlW97ABDecj2eMpThYyj-9uq0mxHT7_g6mSI2uIfB7VlJl85_s7UAQmndxXbc/s1600/error.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVO5wEf1Sp2P-uPnnRL2Ar2Th-P8E5i7o8FqkaCDFgTjdHN9lh4eIxhp033IzzY4R4jjB0-bBEtsAYTxPlW97ABDecj2eMpThYyj-9uq0mxHT7_g6mSI2uIfB7VlJl85_s7UAQmndxXbc/s1600/error.PNG&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;Возможная причина:&lt;/b&gt; не установлен один из необходимых компонентов или не указан путь к Android SDK &lt;br /&gt;
&lt;b&gt;Решение&lt;/b&gt;: см. пункт 1.1. - 1.5.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Проблема:&lt;/b&gt; при запуске команды android ошибка&lt;br /&gt;
&lt;code class=&quot;prettyprint&quot;&gt;android is not recognized as an internal or external command, operable command or batch file &lt;/code&gt; &lt;br /&gt;
&lt;b&gt;Возможная причина:&lt;/b&gt; система не может найти android.bat &lt;br /&gt;
&lt;b&gt;Решение&lt;/b&gt;: см. пункт 1.4.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Проблема:&lt;/b&gt; при запуске команды npm ошибка&lt;br /&gt;
&lt;code&gt;npm&lt;/code&gt;&lt;code class=&quot;prettyprint&quot;&gt; is not recognized as an internal or external command, operable command or batch file&lt;/code&gt;&lt;br /&gt;
&lt;b&gt;Возможная причина: &lt;/b&gt;в переменной PATH не указан путь к npm или не установлен nodejs&lt;br /&gt;
&lt;b&gt;Решение&lt;/b&gt;: см. пункт 2.1 - 2.2.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Проблема:&lt;/b&gt; Eclipse не хочет создавать проект из кода, который сделал phonegap.&lt;br /&gt;
&lt;b&gt;Возможная причина:&lt;/b&gt; вы не сбилдили проект с помощью phonegap.&lt;br /&gt;
&lt;b&gt;Решение:&lt;/b&gt; см. пункт 3.2. &lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/07/phonegap-step-by-step.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDbPaTU3W856Z_VTi6y0Ohibdcjttb_Qq2td0vLv3q5-xxTGUbGv7ksD2yWbXjM2loUJrTvD0xxnC4EncUrVPqS6ZLSTLfKrqmtoQnFIgYVVFvM-IcJ3nejK0pqb60vNPJCoCFTG54nqI/s72-c/Capture.PNG" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-3768785244449124942</guid><pubDate>Wed, 24 Jul 2013 15:34:00 +0000</pubDate><atom:updated>2013-07-24T18:34:50.527+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">bug</category><category domain="http://www.blogger.com/atom/ns#">svn</category><category domain="http://www.blogger.com/atom/ns#">tortoisesvn</category><title>Tortoise svn 1.8: bugged edition</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Эх, черепаха, что ж ты делаешь? Адпейт до последней стабильной версии Tortoise SVN 1.8, который просит для работы Visual SVN, несёт с собой необходимость переконвертировать working directory в новый формат. И старые версии черепашки не понимают этот формат (что вполне ожидаемо).&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8I8DjcwLEEeVF6DLyWEd0Z5xiy5RY3yjjRIJaLUA8OKTWGMSbHY0gEiJELcVDBnCZsahNHiVZSz_VJaBKxjW-Xx_S6iGe6pBosNM7ooSnfL0VB4arZ9Ikmd-i7BY3Z2lZkF34pRMZ2rU/s1600/updateyoursvn.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;83&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8I8DjcwLEEeVF6DLyWEd0Z5xiy5RY3yjjRIJaLUA8OKTWGMSbHY0gEiJELcVDBnCZsahNHiVZSz_VJaBKxjW-Xx_S6iGe6pBosNM7ooSnfL0VB4arZ9Ikmd-i7BY3Z2lZkF34pRMZ2rU/s640/updateyoursvn.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Но при попытке апдейта кода из репозитория сюрприз!&lt;br /&gt;
&lt;b&gt;&lt;span class=&quot;GGYB0KICNUB&quot; id=&quot;t-t&quot;&gt;The PROPFIND response did not include the requested properties&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioAGb6Q1MPCSmdbcvWkheeG4tPyTr4NOQeFaFge1Bxq03CCLqBNDIZVIZC-3YF_FiBbd7Sj2fckkJ5f_A4If-FpxzDAmqONGemTtPChzUB_I0Mjdou0-CSQ_aF9pS8dlNsq160Jha0Ntk/s1600/updateyoursvn2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioAGb6Q1MPCSmdbcvWkheeG4tPyTr4NOQeFaFge1Bxq03CCLqBNDIZVIZC-3YF_FiBbd7Sj2fckkJ5f_A4If-FpxzDAmqONGemTtPChzUB_I0Mjdou0-CSQ_aF9pS8dlNsq160Jha0Ntk/s1600/updateyoursvn2.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;a href=&quot;https://groups.google.com/forum/#!topic/tortoisesvn/o5taYV-bm0c&quot; target=&quot;_blank&quot;&gt;В гугл-группе черепахи&lt;/a&gt; обещается фикс в версии 1.8.1, но на официальном сайте даже нет предупреждения&amp;nbsp; об ошибке, содержащейся в релизе. Вобщем, сюрприз должен быть для всех, а не только для избранных любителей экстрима.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Мораль этого всего такова: не стоит спешить опробовать чужие баги на своей шкуре. С tortoise svn это случалось уже не раз, и, видимо, не раз повторится. Любите своих пользователей, убирайте бажные релизы с серверов или максимально быстро выпускайте баг-фиксы, параллельно предупреждая пользователей об опасности.&amp;nbsp; &lt;/div&gt;
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/07/tortoise-svn-18-bugged-edition.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8I8DjcwLEEeVF6DLyWEd0Z5xiy5RY3yjjRIJaLUA8OKTWGMSbHY0gEiJELcVDBnCZsahNHiVZSz_VJaBKxjW-Xx_S6iGe6pBosNM7ooSnfL0VB4arZ9Ikmd-i7BY3Z2lZkF34pRMZ2rU/s72-c/updateyoursvn.png" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-875072407053714311</guid><pubDate>Fri, 12 Jul 2013 15:15:00 +0000</pubDate><atom:updated>2013-07-12T18:15:54.176+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">java</category><category domain="http://www.blogger.com/atom/ns#">юмор</category><title>ProblemFactory</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7Ct_NhV7I7PKhU289YQidz8hYS1LR9TVxFoLjk15mHGZbp0twZV7Lm8HuNGwwJB4MAoKX6VRDDlfERu_-8knrs_yJVpWwqMc1vZQVb7TIuVb1HmP9q0BMxgfMK_dvKl2IOKlqfXhpleU/s1600/ga7YxrDkbQY.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;480&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7Ct_NhV7I7PKhU289YQidz8hYS1LR9TVxFoLjk15mHGZbp0twZV7Lm8HuNGwwJB4MAoKX6VRDDlfERu_-8knrs_yJVpWwqMc1vZQVb7TIuVb1HmP9q0BMxgfMK_dvKl2IOKlqfXhpleU/s640/ga7YxrDkbQY.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/07/problemfactory.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7Ct_NhV7I7PKhU289YQidz8hYS1LR9TVxFoLjk15mHGZbp0twZV7Lm8HuNGwwJB4MAoKX6VRDDlfERu_-8knrs_yJVpWwqMc1vZQVb7TIuVb1HmP9q0BMxgfMK_dvKl2IOKlqfXhpleU/s72-c/ga7YxrDkbQY.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-3376440942569486549</guid><pubDate>Fri, 12 Jul 2013 15:11:00 +0000</pubDate><atom:updated>2013-07-12T18:11:25.084+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">юмор</category><title>Кодинг на улице</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Ведь так оно и есть. 
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvsbsy1eH18AXqQ2DHdvSaw9bEyqMpjNoGlBPc_RThdt1kmCFnOUuP1xRaTZDErlCBWfWO1yQo0I7vLmLE0nBFfxPvNOd6TTcGcqHsA_h4p7MfZU-5WPKhS-GFbgc0ks0L08zdDJwN1n4/s1600/dtfKAW5PoX8.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvsbsy1eH18AXqQ2DHdvSaw9bEyqMpjNoGlBPc_RThdt1kmCFnOUuP1xRaTZDErlCBWfWO1yQo0I7vLmLE0nBFfxPvNOd6TTcGcqHsA_h4p7MfZU-5WPKhS-GFbgc0ks0L08zdDJwN1n4/s1600/dtfKAW5PoX8.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/07/blog-post_12.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvsbsy1eH18AXqQ2DHdvSaw9bEyqMpjNoGlBPc_RThdt1kmCFnOUuP1xRaTZDErlCBWfWO1yQo0I7vLmLE0nBFfxPvNOd6TTcGcqHsA_h4p7MfZU-5WPKhS-GFbgc0ks0L08zdDJwN1n4/s72-c/dtfKAW5PoX8.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-4619481796588566150</guid><pubDate>Mon, 08 Jul 2013 11:17:00 +0000</pubDate><atom:updated>2013-07-08T14:17:08.334+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">мысли в слух</category><category domain="http://www.blogger.com/atom/ns#">разработка ПО</category><category domain="http://www.blogger.com/atom/ns#">юмор</category><title>Перед...</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Перед началом очередного проекта&lt;br /&gt;
Перед добавлением нового функционала&lt;br /&gt;
Перед улучшением работающего кода&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirTJHZoF86C0mof8YSJA9d_llhr2SFRgjmGqN3KyNcSDQXQrj6fNmheE0B514HFCaVcwb66wuS-2koVRivxK0R4-g5mGUGVTnjSr2-81CglAemMDbCjSQEwlzD0o5fQ4ICpnvocJgPwrE/s1600/90.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirTJHZoF86C0mof8YSJA9d_llhr2SFRgjmGqN3KyNcSDQXQrj6fNmheE0B514HFCaVcwb66wuS-2koVRivxK0R4-g5mGUGVTnjSr2-81CglAemMDbCjSQEwlzD0o5fQ4ICpnvocJgPwrE/s1600/90.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/07/blog-post.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirTJHZoF86C0mof8YSJA9d_llhr2SFRgjmGqN3KyNcSDQXQrj6fNmheE0B514HFCaVcwb66wuS-2koVRivxK0R4-g5mGUGVTnjSr2-81CglAemMDbCjSQEwlzD0o5fQ4ICpnvocJgPwrE/s72-c/90.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-3201167328399101696</guid><pubDate>Wed, 12 Jun 2013 14:42:00 +0000</pubDate><atom:updated>2013-06-12T17:42:30.651+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">atdd</category><category domain="http://www.blogger.com/atom/ns#">bdd</category><category domain="http://www.blogger.com/atom/ns#">phpunit</category><category domain="http://www.blogger.com/atom/ns#">tdd</category><category domain="http://www.blogger.com/atom/ns#">tddigest</category><title>TDDigest e05</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVBraCbZQGPharUxFI5nsxNP0m5juGbPHV7Ta9qd-m-6EhJuX2hY2UyyUc5uTZRJ2Fa562FfB0-p6IkKd-slEHe-5IdAAFUjKVpfE0r9HtFzhqIvKB-hAnE0ss-bh2Tkk_4ucoDa6WnQ0/s1600/TDD.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVBraCbZQGPharUxFI5nsxNP0m5juGbPHV7Ta9qd-m-6EhJuX2hY2UyyUc5uTZRJ2Fa562FfB0-p6IkKd-slEHe-5IdAAFUjKVpfE0r9HtFzhqIvKB-hAnE0ss-bh2Tkk_4ucoDa6WnQ0/s1600/TDD.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Интереснейший пост от компании Badoo об &lt;a href=&quot;http://habrahabr.ru/company/badoo/blog/181488/&quot; target=&quot;_blank&quot;&gt;&quot;Оптимальной параллелизации юнит-тество или 17000 тестов за 4 минуты&quot;&lt;/a&gt; #ru&lt;/div&gt;
BDD in Action: &lt;a href=&quot;http://michael-whelan.net/bddfy-in-action/roll-your-own-testing-framework&quot;&gt;Часть 1&lt;/a&gt;, &lt;a href=&quot;http://michael-whelan.net/bddfy-in-action/roll-your-own-testing-framework-2&quot;&gt;Часть 2&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://smspillaz.wordpress.com/2013/05/30/let-your-tests-tell-you-when-your-code-design-sucks/&quot;&gt;Let your tests tell you when your code design sucks.&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/&quot;&gt;Why Not To Want 100% Code Coverage&lt;/a&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Tips and tricks для&amp;nbsp; более эффективного использования phpUnit в слайдах &lt;a href=&quot;http://thephp.cc/dates/2013/international-php-conference-spring-edition/phpunit-best-practices&quot;&gt;PHPUnit best practicies&lt;/a&gt;. А так же, &lt;a href=&quot;http://habrahabr.ru/post/183010/&quot; target=&quot;_blank&quot;&gt;чем хорош phpUnit для создания mock-объектов&lt;/a&gt; - хорошая статья на Хабре. И, закрывая тему phpUnit, &lt;a href=&quot;http://net.tutsplus.com/tutorials/php/parallel-testing-for-phpunit-with-paratest/&quot; target=&quot;_blank&quot;&gt;Parallel testing for phpUnit with ParaTest&lt;/a&gt;&lt;/div&gt;
&lt;a href=&quot;http://www.youtube.com/watch?feature=player_embedded&amp;amp;v=CswgfGhnTg8&quot;&gt;TDD Javascript with Jasmine&lt;/a&gt; #video&amp;nbsp; #en&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Статья &lt;a href=&quot;http://www.leadingagile.com/2013/06/building-the-right-software-right-should-be-easy-right/&quot;&gt;Building the right software…right, It’s easy…RIGHT?&lt;/a&gt; с разъяснением разницы, что значит делать правильно и делать правильное. Путаница возникает, в основном, из-за использоания ATDD и BDD и TDD... Слишком много букв D, всё driven, только в какую сторону? Автор предлагает следующую структуру: сначала используется BDD - для определения целей, за ним - ATDD - для реализации целей, и потом TDD - для качественной реализации.&lt;br /&gt;
И небольшое видео, в котором объяняется разница между BDD и TDD:&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/mT8QDNNhExg&quot; width=&quot;560&quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Все знают мантру TDD &quot;Red-Green-Refactoring&quot;, но как мы определяем, что рефакторинг нужен? И как найти золотую середину между минимизацией времени, затрачиваемом на разработку, и качеством кода, который придеся кому-то сопровождать в будущем?&amp;nbsp; Об этом речь в видео (а заодно и слайдах) &lt;a href=&quot;http://tx.pignata.com/2013/04/mwrc-code-smells-talk.html&quot;&gt;Code Smells: Your Refactoring Cheat Codes&lt;/a&gt; #en #video #tdd #refactoring&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Правильный подход к вопросу о unit-тестировании кода на &lt;a href=&quot;http://stackoverflow.com/questions/16826582/how-do-i-architect-my-classes-for-easier-unit-testing&quot;&gt;stackoverflow&lt;/a&gt;. #en #php&lt;/div&gt;
О синергии тестируемости кода и дизайна приложения #video #en&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;300&quot; mozallowfullscreen=&quot;&quot; src=&quot;http://player.vimeo.com/video/15007792&quot; webkitallowfullscreen=&quot;&quot; width=&quot;400&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
Обсуждение трёх подходов к mobile testing:
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/5JYg1kT8MZA&quot; width=&quot;560&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/06/tddigest-e05.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVBraCbZQGPharUxFI5nsxNP0m5juGbPHV7Ta9qd-m-6EhJuX2hY2UyyUc5uTZRJ2Fa562FfB0-p6IkKd-slEHe-5IdAAFUjKVpfE0r9HtFzhqIvKB-hAnE0ss-bh2Tkk_4ucoDa6WnQ0/s72-c/TDD.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-5723245758386774561</guid><pubDate>Wed, 29 May 2013 15:10:00 +0000</pubDate><atom:updated>2013-05-29T18:10:32.525+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">mock</category><category domain="http://www.blogger.com/atom/ns#">msswit2013</category><category domain="http://www.blogger.com/atom/ns#">tdd</category><category domain="http://www.blogger.com/atom/ns#">tddigest</category><title>TDDigest e04</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVBraCbZQGPharUxFI5nsxNP0m5juGbPHV7Ta9qd-m-6EhJuX2hY2UyyUc5uTZRJ2Fa562FfB0-p6IkKd-slEHe-5IdAAFUjKVpfE0r9HtFzhqIvKB-hAnE0ss-bh2Tkk_4ucoDa6WnQ0/s1600/TDD.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVBraCbZQGPharUxFI5nsxNP0m5juGbPHV7Ta9qd-m-6EhJuX2hY2UyyUc5uTZRJ2Fa562FfB0-p6IkKd-slEHe-5IdAAFUjKVpfE0r9HtFzhqIvKB-hAnE0ss-bh2Tkk_4ucoDa6WnQ0/s1600/TDD.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
В сегодняшней подборке материалов из мира TDD много видео интересных выступлений и интервью.&lt;br /&gt;
Видео с выступления #Сергея Теплякова на msswit &quot;&lt;a href=&quot;http://www.techdays.ru/videos/6831.html&quot; tabindex=&quot;0&quot; target=&quot;_blank&quot;&gt;Тестируемая архитектура: моки, стабы, рефакторинг&lt;/a&gt;&quot; #video #ru #mock #design #msswit&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&quot;&lt;a href=&quot;http://codebetter.com/brendantompkins/2013/05/24/tdd-i-learned/&quot; target=&quot;_blank&quot;&gt;TDD I learned...&lt;/a&gt;&quot; - автор рассказывает о своих неудачных попытках писать тесты и полном непонимании бенефитов TDD до тех пор, пока не натолкнулся на мастер-класс Roy Osherove по TDD. &lt;a href=&quot;https://www.udemy.com/tdd-in-net-with-roy-osherove/&quot; target=&quot;_blank&quot;&gt;Из видео, которое идет более 9 часов&lt;/a&gt;, автор вынес для себя много полезного, понял разницу между интеграционными тестами и юнит тестами, и впечатлился AAA-подходом (Arrange, Act, Assert):&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
This approach, by eliminating assert code
 intermixed with code that sets up or acts upon your objects, reduces 
smelly tests by separating what is being tested from all the other 
stuff.&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
Такой подход разделяет проверку (assert) результата, инициализацию объектов (arrange) и действия над ними (act), отделяя то, что нужно протестировать, от всего остального, тем самым устраняя дурной &quot;запашок-с&quot; тестов. &lt;/blockquote&gt;
&lt;/div&gt;
#en #tdd&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Интересное интервью со Стивом Фрименом и Нэтом Прайсом, авторами книги &quot;&lt;a href=&quot;http://www.softwaredevelopmentbooks.com/programming/growing-object-oriented-software-guided-by-tests/&quot;&gt;Growing Object-Oriented Software, Guided by Tests&lt;/a&gt;&quot; &lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;iframe allowfullscreen=&#39;allowfullscreen&#39; webkitallowfullscreen=&#39;webkitallowfullscreen&#39; mozallowfullscreen=&#39;mozallowfullscreen&#39; width=&#39;320&#39; height=&#39;266&#39; src=&#39;https://www.youtube.com/embed/KTraKQ9KOnY?feature=player_embedded&#39; frameborder=&#39;0&#39;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a href=&quot;http://www.lazycoder.com/weblog/2013/05/23/how-do-you-start-a-new-project-with-tdd/&quot; target=&quot;_blank&quot;&gt;How do you start a new project with TDD?&lt;/a&gt; -&amp;nbsp; своеобразный подход к настройке среды для нового проекта. #en &lt;br /&gt;
&lt;a href=&quot;http://www.confreaks.com/videos/2433-railsconf2013-bdd-and-acceptance-testing-with-rspec-capybara&quot; target=&quot;_blank&quot;&gt;BDD and Acceptance Testing with RSpec &amp;amp; Capybara&lt;/a&gt; #en #video #ruby #bdd #rspec&lt;br /&gt;
&lt;a href=&quot;http://www.tekritisoftware.com/drupal-unit-testing-with-simpletest-module&quot; target=&quot;_blank&quot;&gt;Drupal unit testing&lt;/a&gt; #en #drupal #php&lt;br /&gt;
Беседа о &lt;a href=&quot;https://blog.engineyard.com/2013/a-conversation-about-testing-in-php&quot; target=&quot;_blank&quot;&gt;unit-тестировании в php&lt;/a&gt; #en #php #unit-testing&lt;br /&gt;
&lt;a href=&quot;http://youtu.be/L-lLSi4lXEY&quot;&gt;Юнит-тестирование в CakePhp&lt;/a&gt; #en #php #unit-testing #video &lt;br /&gt;
&lt;a href=&quot;http://ffbit.com/blog/2013/05/27/junit-slash-testng-testing-spring-security-with-spring-mvc-test-framework/&quot;&gt;JUnit / TestNG Testing Spring Security With Spring MVC Test Framework&lt;/a&gt;
&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Инструменты&lt;/h3&gt;
&lt;a href=&quot;http://zubte.com/blog/mockery-an-alternative-mocking-framework-for-unit-testing/&quot; target=&quot;_blank&quot;&gt;Mockery&lt;/a&gt; - ещё один mock-фреймворк для unit-тестов&lt;br /&gt;
&lt;a href=&quot;https://github.com/jubianchi/atoum.js&quot;&gt;atoum.js&lt;/a&gt; - стильный, модный, молодёжный ;) фреймфорк для тестирования PHP5.3+ теперь и для js&lt;br /&gt;
&lt;a href=&quot;http://www.jetmore.org/john/code/swaks/faq.html&quot;&gt;Swaks&lt;/a&gt; - швейцарский нож для тестирования SMTP&lt;br /&gt;
&lt;a href=&quot;http://www.jetbrains.com/dotcover/&quot;&gt;dotCover&lt;/a&gt; - тест-ранер, а так же инструмент для&amp;nbsp; сбора аналитики о степени покрытия кода тестами для VS от JetBrains (правда, платный)&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/05/tddigest-e04.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVBraCbZQGPharUxFI5nsxNP0m5juGbPHV7Ta9qd-m-6EhJuX2hY2UyyUc5uTZRJ2Fa562FfB0-p6IkKd-slEHe-5IdAAFUjKVpfE0r9HtFzhqIvKB-hAnE0ss-bh2Tkk_4ucoDa6WnQ0/s72-c/TDD.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-8568640747117668849</guid><pubDate>Wed, 22 May 2013 15:55:00 +0000</pubDate><atom:updated>2013-05-22T18:55:11.064+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">bdd</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">coffeescript</category><category domain="http://www.blogger.com/atom/ns#">jasmine</category><category domain="http://www.blogger.com/atom/ns#">mocha</category><category domain="http://www.blogger.com/atom/ns#">msswit2013</category><category domain="http://www.blogger.com/atom/ns#">php</category><category domain="http://www.blogger.com/atom/ns#">qunit</category><category domain="http://www.blogger.com/atom/ns#">tdd</category><category domain="http://www.blogger.com/atom/ns#">tddigest</category><title>TDDigest e03</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVBraCbZQGPharUxFI5nsxNP0m5juGbPHV7Ta9qd-m-6EhJuX2hY2UyyUc5uTZRJ2Fa562FfB0-p6IkKd-slEHe-5IdAAFUjKVpfE0r9HtFzhqIvKB-hAnE0ss-bh2Tkk_4ucoDa6WnQ0/s1600/TDD.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVBraCbZQGPharUxFI5nsxNP0m5juGbPHV7Ta9qd-m-6EhJuX2hY2UyyUc5uTZRJ2Fa562FfB0-p6IkKd-slEHe-5IdAAFUjKVpfE0r9HtFzhqIvKB-hAnE0ss-bh2Tkk_4ucoDa6WnQ0/s1600/TDD.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Для начала разберёмся, как писать &lt;a href=&quot;http://alistapart.com/article/writing-testable-javascript&quot; target=&quot;_blank&quot;&gt;тестируемый код на javascript&lt;/a&gt;, и поговорим о том, как тестировать полученный код с помощью &lt;a href=&quot;http://css.dzone.com/articles/simple-javascript-testing&quot; target=&quot;_blank&quot;&gt;QUnit&lt;/a&gt;, а так же как наслаждаться процессом &lt;a href=&quot;http://www.htmlgoodies.com/beyond/javascript/how-mocha-makes-testing-asynchronous-javascript-processes-fun.html&quot; target=&quot;_blank&quot;&gt;тестирования асинхронного javascript с помощью Mocha&lt;/a&gt; #javascript #en #mocha&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Туториал о том, как &lt;a href=&quot;http://net.tutsplus.com/tutorials/php/how-to-write-testable-and-maintainable-code-in-php/&quot; target=&quot;_blank&quot;&gt;писать тестируемый и поддерживаемый код на php&lt;/a&gt;, чего избегать в коде, а что, наоборот, является правильным подходом. Ещё серия туториалов, детально раскрывающих процесс &lt;a href=&quot;https://jtreminio.com/2013/03/unit-testing-tutorial-introduction-to-phpunit/&quot; target=&quot;_blank&quot;&gt;юнит-тестирования с PHPUnit&lt;/a&gt;. Рассматриваются такие темы, как написание полезного теста (!), моки, стабы, dependency injection, тестирование закрытых методов класса (если уж очень нужно), перегруженные конструкторы и почему 100% покрытие кода не так уж и важно. #en #php #phpunit&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Roy Osherove, автор &quot;The art of unit testing&quot;, переосмысливает юнит-тесты. В &lt;a href=&quot;http://www.techdays.ru/videos/6832.html&quot; target=&quot;_blank&quot;&gt;видео&lt;/a&gt; с конференции Microsoft Swit он рассказывает, как изменились его взгляды на такие вопросы, как: что такое юнит-тест? нужны ли изоляционные фреймворки? внедрение зависимостей через конструктор или через свойства? Делится опытом, почерпнутом из мира ruby . #video #en #royosherove&lt;br /&gt;
&lt;iframe frameborder=&quot;0&quot; mce_src=&quot;http://www.techdays.ru/videos/6832.html?isEmbedded=true&quot; scrolling=&quot;no&quot; src=&quot;http://www.techdays.ru/videos/6832.html?isEmbedded=true&quot; style=&quot;height: 317px; width: 555px;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;a href=&quot;https://efendibooks.com/minibooks/testing-with-coffeescript&quot; target=&quot;_blank&quot;&gt;BDD&amp;nbsp;+ CoffeeScript + Jasmine&lt;/a&gt; = прекрасно! Небольшая книга, демонстрирующая на примере создания скрипта корзины для магазина процесс разработки в BDD-стиле на CoffeeScript #coffeescript #bdd #jasmine&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Раз уж зашла речь о BDD, то сравним&amp;nbsp; &lt;a href=&quot;http://blog.mattwynne.net/2012/11/20/tdd-vs-bdd/&quot; target=&quot;_blank&quot;&gt;TDD vs BDD&lt;/a&gt;
 А вы на чьей стороне? Авторы статьи пришли к логичному выводу, что BDD не так 
уж сильно отличается от TDD, добавляя лишь ясность того, что тестируется, тем
 самым делая TDD более успешным. #tdd #bdd&lt;/div&gt;
&lt;a href=&quot;http://www.testingtv.com/2013/05/17/acceptance-test-driven-android/&quot; target=&quot;_blank&quot;&gt;Acceptance Test Driven Android&lt;/a&gt; #en #tdd #android&lt;br /&gt;
&lt;a href=&quot;http://tech.pro/tutorial/1276/servicestack-and-ravendb-end-to-end-testing&quot; target=&quot;_blank&quot;&gt;ServiceStack and&amp;nbsp; RavenDB end to end testing&lt;/a&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Цикл статей &quot;Автоматизированное тестирование веб-приложения (MS Unit Testing Framework + Selenium WebDriver C#)&quot; &lt;a href=&quot;http://habrahabr.ru/post/178321/&quot; target=&quot;_blank&quot;&gt;Часть 1&lt;/a&gt;, &lt;a href=&quot;http://habrahabr.ru/post/180047/&quot; target=&quot;_blank&quot;&gt;Часть 2.1&lt;/a&gt;, &lt;a href=&quot;http://habrahabr.ru/post/180357/&quot; target=&quot;_blank&quot;&gt;Часть 2.2&lt;/a&gt;. #msunit #csharp&lt;/div&gt;
&lt;a href=&quot;http://www.clemensreijnen.nl/post/2013/05/17/Testing-in-one-week-sprints-hierarchy-backlog-items-and-test-coverage.aspx&quot; target=&quot;_blank&quot;&gt;Testing in one week sprints, hierarchy backlog items and test coverage&lt;/a&gt;.
&lt;br /&gt;
И на закуску интересная статистика &lt;a href=&quot;http://www.opennet.ru/opennews/art.shtml?num=36877&quot;&gt;сравнения качества кода открытых и проприетарных проектов&lt;/a&gt;&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Инструменты&lt;/h3&gt;
&lt;a href=&quot;http://andresdominguez.github.io/ddescriber/&quot; target=&quot;_blank&quot;&gt;DDescriber&lt;/a&gt; - плагин для Jasmine для упрощения тестирования&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/05/tddigest-e03.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVBraCbZQGPharUxFI5nsxNP0m5juGbPHV7Ta9qd-m-6EhJuX2hY2UyyUc5uTZRJ2Fa562FfB0-p6IkKd-slEHe-5IdAAFUjKVpfE0r9HtFzhqIvKB-hAnE0ss-bh2Tkk_4ucoDa6WnQ0/s72-c/TDD.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-3970807908683768256</guid><pubDate>Wed, 15 May 2013 07:59:00 +0000</pubDate><atom:updated>2013-05-15T10:59:13.640+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">antipattern</category><category domain="http://www.blogger.com/atom/ns#">php</category><category domain="http://www.blogger.com/atom/ns#">phpunit</category><category domain="http://www.blogger.com/atom/ns#">singleton</category><category domain="http://www.blogger.com/atom/ns#">SublimeText 2</category><category domain="http://www.blogger.com/atom/ns#">tdd</category><category domain="http://www.blogger.com/atom/ns#">tddigest</category><category domain="http://www.blogger.com/atom/ns#">visual studio</category><title>TDDigest e02</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVBraCbZQGPharUxFI5nsxNP0m5juGbPHV7Ta9qd-m-6EhJuX2hY2UyyUc5uTZRJ2Fa562FfB0-p6IkKd-slEHe-5IdAAFUjKVpfE0r9HtFzhqIvKB-hAnE0ss-bh2Tkk_4ucoDa6WnQ0/s1600/TDD.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVBraCbZQGPharUxFI5nsxNP0m5juGbPHV7Ta9qd-m-6EhJuX2hY2UyyUc5uTZRJ2Fa562FfB0-p6IkKd-slEHe-5IdAAFUjKVpfE0r9HtFzhqIvKB-hAnE0ss-bh2Tkk_4ucoDa6WnQ0/s1600/TDD.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Открывает второй выпуск tddigest немного филосовский пост &lt;a href=&quot;http://www.grobmeier.de/the-10-rules-of-a-zen-programmer-03022012.html#.UY3VecpaiSr&quot; target=&quot;_blank&quot;&gt;&quot;10 Правил Дзен-Программиста&quot;&lt;/a&gt; от&amp;nbsp;Christian Grobmeier #en #zen&lt;/div&gt;
Размышления на тему &lt;a href=&quot;http://therealadam.com/2013/01/03/design-for-test-vs-design-for-api/&quot; target=&quot;_blank&quot;&gt;&quot;Design for tests vs Design for API&quot;&lt;/a&gt; #en #tdd #ruby&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Очередные tips &amp;amp; tricks от php-девелоперов. В &lt;a href=&quot;http://sly-and-fluffy.blogspot.com/2013/05/e01.html&quot; target=&quot;_blank&quot;&gt;прошлый раз&lt;/a&gt; нам показывали, как тестить защищённые методы класса, а в этот раз говорят о том, как надо &lt;a href=&quot;http://engineering.zumba.com/2012/11/26/singleton-class-phpunit-mocking/&quot; target=&quot;_blank&quot;&gt;мокать singleton с помощью PHPUnit&lt;/a&gt;. Забавно, ведь даже на самом &lt;a href=&quot;http://php.net/manual/de/language.oop5.patterns.php&quot; target=&quot;_blank&quot;&gt;php.net &lt;/a&gt;красным написано: Ахтунг! Берегись синглтона! (шутки в сторону) А теперь серьёзно, когда может пригодиться такой подход? Я вижу один случай - есть база legacy кода, которую нужно поддерживать. Рефакторить код или вносить изменения без тестов -&amp;nbsp; смело, но глупо. Поэтому приходится иногда заниматься таким: мокать синглоны или чего ещё хуже выдумывать. #php #phpunit #antipattern&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Наверное, из .Net мира все знают о NDepend. В грядущую версию анализатора будет добавлено новое правило в категорию &quot;Purity – Immutability – Side-Effects&quot;. Звучит правило так &quot;Don’t assign a field from many methods&quot;. Причины появления этого правила, симптомы и возможные проблемы - &lt;a href=&quot;http://codebetter.com/patricksmacchia/2013/05/13/dont-assign-a-field-from-many-methods/&quot; target=&quot;_blank&quot;&gt;в заметке на codebetter&lt;/a&gt;. Ещё один экземплярчик &quot;кода с душком&quot;.&lt;br /&gt;
&lt;a href=&quot;http://starkandwayne.com/articles/2013/05/07/tdd-your-devops-with-test-kitchen/&quot; target=&quot;_blank&quot;&gt;TDD test-kitchen 1.0&lt;/a&gt; &lt;i&gt;is probably the best demonstration I&#39;ve seen so far showing the TDD process for cookbook development.&lt;/i&gt; Fletcher Nichol &lt;/div&gt;
Слайды c прошедшей RailsConf &quot;&lt;a href=&quot;https://speakerdeck.com/skmetz/magic-tricks-of-testing-railsconf&quot; target=&quot;_blank&quot;&gt;Magic Tricks of Testing&quot;&lt;/a&gt;&amp;nbsp; от &lt;a href=&quot;https://speakerdeck.com/skmetz&quot;&gt;Sandi Metz&lt;/a&gt; #ruby #tests #slides #en&lt;br /&gt;
Слайды &quot;7 шагов к вашему первому тесту&quot; от&amp;nbsp;Gil Zilberfeld. Напомнило серию &quot;Ералаша&quot; &lt;a href=&quot;http://rutube.ru/video/563836380401b09b7151d37f137483dd/&quot; target=&quot;_blank&quot;&gt;&quot;Путёвка в жизнь&quot;&lt;/a&gt;. #test #slides #en&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;356&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; mozallowfullscreen=&quot;&quot; scrolling=&quot;no&quot; src=&quot;http://www.slideshare.net/slideshow/embed_code/20795129&quot; style=&quot;border-width: 1px 1px 0; border: 1px solid #CCC; margin-bottom: 5px;&quot; webkitallowfullscreen=&quot;&quot; width=&quot;427&quot;&gt; &lt;/iframe&gt; &lt;br /&gt;
&lt;div style=&quot;margin-bottom: 5px;&quot;&gt;
&lt;b&gt; &lt;a href=&quot;http://www.slideshare.net/gilzilberfeld/sela-presentation&quot; target=&quot;_blank&quot; title=&quot;7 Steps for writing your first test&quot;&gt;7 Steps for writing your first test&lt;/a&gt; &lt;/b&gt; from &lt;b&gt;&lt;a href=&quot;http://www.slideshare.net/gilzilberfeld&quot; target=&quot;_blank&quot;&gt;Gil Zilberfeld&lt;/a&gt;&lt;/b&gt; &lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
В дополнение к слайдам &lt;a href=&quot;http://www.typemock.com/unit-testing-dot-net&quot; target=&quot;_blank&quot;&gt;заметка&lt;/a&gt; о том, как написать первый юнит тест в Visual Studio для .Net. Уточню, что, начиная с 11-ой версии, в VS появилась крутая возможность с помощью Unit test adapter подключать сторонние тест-фреймворки в Unit Test Explorer. Я даже как-то рассказывала о том, &lt;a href=&quot;http://sly-and-fluffy.blogspot.com/2012/03/visual-studio-11-xunitnet.html&quot; target=&quot;_blank&quot;&gt;как подключить xUnit.Net&lt;/a&gt; без TestDriven.Net к студии. #xunit #VisualStudio&lt;/div&gt;
Видео &quot;&lt;a href=&quot;http://www.youtube.com/watch?v=4BXpi7056RM&amp;amp;feature=youtu.be&amp;amp;a&quot; target=&quot;_blank&quot;&gt;Hands-On Unit Testing With PHPUnit&lt;/a&gt;&quot; #php #en #video&lt;br /&gt;
Видео &quot;&lt;a href=&quot;http://www.youtube.com/watch?v=TceLCWRBG7M&amp;amp;feature=youtu.be&quot; target=&quot;_blank&quot;&gt;Sublime Text 2 For PHP Development: Testing&lt;/a&gt;&quot; #php #sublimetext #en #video&lt;br /&gt;
&lt;a href=&quot;http://www.youtube.com/watch?v=xyaitZh4grI&amp;amp;list=PL4D06VU7VvodJcnaM_jSiZHz-0mzL8jRS&quot; target=&quot;_blank&quot;&gt;Много интересных видео&lt;/a&gt; с прошедшей недавно Test Automation Days #ru #video&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;a href=&quot;http://ru.selenide.org/2013/04/23/what-is-selenide/&quot; target=&quot;_blank&quot;&gt;Знакомимся с Selenide&lt;/a&gt; -&amp;nbsp; обёрткой вокруг Selenium WebDriver, дающей удобный синтаксис и решающей большинство проблем, связанных с Ajax и таймаутами. &lt;a href=&quot;http://www.youtube.com/watch?feature=player_embedded&amp;amp;v=4u12d_X2-WA&quot; target=&quot;_blank&quot;&gt;Видео доклада про Selenide&lt;/a&gt; с&amp;nbsp; недавней конференции SeleniumCamp 2013 в Киеве, а так же много примеров реализации одних и тех же вещей &lt;a href=&quot;https://github.com/codeborne/selenide/wiki/Selenide-vs-Selenium&quot; target=&quot;_blank&quot;&gt;на Selenide и на средствами голого Selenium. &lt;/a&gt;#ui-testing #selenium #selenide&lt;br /&gt;
&lt;a href=&quot;http://grzesiek-galezowski.github.io/tdd-ebook/&quot; target=&quot;_blank&quot;&gt;TDD ebook&lt;/a&gt; &lt;br /&gt;
И на закуску &lt;a href=&quot;http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks&quot; target=&quot;_blank&quot;&gt;список тестовых фреймворков&lt;/a&gt; - есть из чего выбрать даже гурманам.&amp;nbsp; &lt;/div&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Инструментарий&lt;/h3&gt;
&lt;a href=&quot;http://www.telerik.com/campaigns/justmock/just-mock-mocking-framework.aspx&quot; target=&quot;_blank&quot;&gt;JustMock&lt;/a&gt; - мок-фреймворк от Telerik.&lt;br /&gt;
&lt;a href=&quot;https://github.com/banderous/Uniject&quot; target=&quot;_blank&quot;&gt;Uniject&lt;/a&gt; - тестовый фреймвор для Unity3D&lt;br /&gt;
&lt;a href=&quot;https://github.com/codeborne/selenide&quot; target=&quot;_blank&quot;&gt;Selenide&lt;/a&gt; -&amp;nbsp;библиотека для написания UI тестов (Java). &lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/05/tddigest-e02.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVBraCbZQGPharUxFI5nsxNP0m5juGbPHV7Ta9qd-m-6EhJuX2hY2UyyUc5uTZRJ2Fa562FfB0-p6IkKd-slEHe-5IdAAFUjKVpfE0r9HtFzhqIvKB-hAnE0ss-bh2Tkk_4ucoDa6WnQ0/s72-c/TDD.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-3329849939605499681</guid><pubDate>Wed, 08 May 2013 14:40:00 +0000</pubDate><atom:updated>2013-05-08T17:53:53.402+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">coffeescript</category><category domain="http://www.blogger.com/atom/ns#">переводы</category><title>10 особенностей CoffeeScript, о которых вы могли не знать</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgG3Ix0TbSz9V2TVdDJCppioXbheWcGotFaoBcoSCQ8cRix05DYUeLUX2G4lqjAD2xehCn7M0vzKuT_-3pAzhpi3E2F3j8dCPXuXZA84mXG5ehp-6tyCTlsO0RG-5GKTfK0Ekr0aCTJnOw/s1600/a_8467231b.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgG3Ix0TbSz9V2TVdDJCppioXbheWcGotFaoBcoSCQ8cRix05DYUeLUX2G4lqjAD2xehCn7M0vzKuT_-3pAzhpi3E2F3j8dCPXuXZA84mXG5ehp-6tyCTlsO0RG-5GKTfK0Ekr0aCTJnOw/s1600/a_8467231b.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Немного вольный перевод статьи &quot;&lt;a href=&quot;http://www.jacopretorius.net/2013/05/10-coffeescript-features-you-might-not-know.html&quot; target=&quot;_blank&quot;&gt;10 CoffeeScript Features You Might Not Know&lt;/a&gt;&quot; by Jaco Pretorius. &lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
На этой неделе я потратил некоторое времени на изучение ресурсов о CoffeeScript, которые могли бы быть использованы для обучения клиента, и успел открыть для себя новые возможности CoffeeScript, о которых я  раньше не знал или знал, но забыл.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3 style=&quot;text-align: justify;&quot;&gt;
Итерации&lt;/h3&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Наверно, вам известен стандартный способ перебора элементов списка.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;code class=&quot;prettycode&quot;&gt;
for name in [&#39;Tom&#39;,&#39;Dick&#39;,&#39;Harry&#39;]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;alert &quot;Hi, #{name}&quot;&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Но знали ли вы, что можно получить индекс текущего элемента, добавив экстра-аргумент?&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;for name, i in [&#39;Tom&#39;,&#39;Dick&#39;,&#39;Harry&#39;]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;alert &quot;Hi, #{name} - you are number #{i}&quot;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Групповые аргументы (splatting)&lt;/h3&gt;
JavaScript (и CoffeeScript тоже) не обязывают передавать в функцию правильное количество аргументов. В примере ниже лишние аргументы будут просто отброшены: &lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;planets = (first, second, third) -&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;alert third&lt;br /&gt;&lt;br /&gt;
   
planets &#39;Mercury&#39;, &#39;Venus&#39;, &#39;Earth&#39;, &#39;Mars&#39;, &#39;Jupiter&#39;&lt;br /&gt;
# alert will be &#39;Earth&#39;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Но знали ли вы, что CoffeeScript поддерживает групповые аргументы? (Групповые аргументы обозначаются добавление троеточия - прим. переводчика)&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;planets = (first, second, others...) -&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;alert others&lt;br /&gt;&lt;br /&gt;
 
planets &#39;Mercury&#39;, &#39;Venus&#39;, &#39;Earth&#39;, &#39;Mars&#39;, &#39;Jupiter&#39;&lt;br /&gt;
# alert will be &#39;Earth&#39;,&#39;Mars&#39;,&#39;Jupiter&#39;&lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Генераторы (сomprehensions)&lt;/h3&gt;
Coffeescript также поддерживает генераторы - похоже на map в Ruby.&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;class Person&lt;br /&gt;
&amp;nbsp;&amp;nbsp;constructor: (name, email) -&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@name = name&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@email = email&lt;br /&gt;&lt;br /&gt;
 
userEmails =&lt;br /&gt;
&amp;nbsp;&amp;nbsp;tom: &#39;tom@example.com&#39;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;dick: &#39;dick@example.com&#39;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;harry: &#39;harry@example.com&#39;&lt;br /&gt;&lt;br /&gt;
 
contacts = for name, email of userEmails&lt;br /&gt;
&amp;nbsp;&amp;nbsp;new Person(name,email)&lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Реструктурирующее присваивание&lt;/h3&gt;
Деструктивное присваивание - ещё один способ реализации множественного присваивания. Вы можете использовать это для переключения значений между двумя переменными одной операцией:&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;one = 1&lt;br /&gt;
two = 2&lt;br /&gt;
[one, two] = [two, one]&lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
Этот приём можно так же использовать для присваивания результата функции нескольким переменным:&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;date = -&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;[25,&#39;April&#39;,2013]&lt;br /&gt;&lt;br /&gt;
 
[day, month, year] = date()&lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
И даже так - работает:&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;person =&lt;br /&gt;
&amp;nbsp;&amp;nbsp;name: &#39;John&#39;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;email: &#39;john@example.com&#39;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;address:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;street: [&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&#39;123 Main Street&#39;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&#39;Apt 8B&#39;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;city: &#39;Gotham&#39;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;zip: &#39;8442&#39;&lt;br /&gt;&lt;br /&gt;
 
{ address: { street: [_, apartment], city } } = person&lt;/code&gt;&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Реструктурирующее присваивание + генераторы&lt;/h3&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Реструктурирующее присваивание так же работает в паре с генераторами, что даёт мощный инструмент при работе с массивами переменной длины.&lt;/div&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;daysOfTheWeek = &quot;Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday&quot;&lt;br /&gt;
 
[first, rest..., last] = daysOfTheWeek.split &#39;,&#39;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;# прим. переводчика:&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;# first = &quot;Monday&quot;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;# rest = [&quot;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;Tuesday&quot;,&quot;Wednesday&quot;,&quot;Thursday&quot;,&quot;Friday&quot;,&quot;Saturday&lt;/code&gt;&quot;]&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;# last = &quot;Sunday&quot; &lt;/code&gt;&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Цепочки сравнений&lt;/h3&gt;
Coffeescript так же поддерживает цепочки сравнений (позаимствовано из Python), что позволяет легко проверить, находится ли значение в заданном диапазоне:&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;temperature = 72&lt;br /&gt;
niceDay = 82 &amp;gt; temperature &amp;gt; 68&lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Встроенные документы (Block strings)&lt;/h3&gt;
Вы, наверное, знаете, что Coffeescript поддерживает интерполяцию строк (синтаксис такой же, как в Ruby).&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;name = &quot;John&quot;&lt;br /&gt;
surname = &quot;Doe&quot;&lt;br /&gt;
 
greeting = &quot;Hi, #{name} #{surname}&quot;&lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;
Но знали ли вы, что CoffeeScript поддерживает встроенные документы? Это очень полезная штука для текста, где важны пробелы и отступы, т.к. формат текста внутри встроенного документа сохраняется:&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;html = &quot;&quot;&quot;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;p&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Hi, #{name} #{surname}&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;&quot;&quot;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Псевдоним @&lt;/h3&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Вы, наверное, знаете, что @ - это псевдоним для &lt;i&gt;this&lt;/i&gt;. Но знали ли вы, что в CoffeeScript есть подобный псевдоним и для доступа к прототипу класса?&lt;/div&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;String::pipeDelimited = -&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;@split &#39;|&#39;&lt;br /&gt;&lt;br /&gt;
 
alert &quot;ABC|abc&quot;.pipeDelimited()&lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Привязка параметров к свойствам&lt;/h3&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
CoffeeScript&amp;nbsp; позволяет нам делать привязку параметров к свойствам с помощью @. Например, часто нужно установить свойство в конструкторе:&lt;/div&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;class Person&lt;br /&gt;
&amp;nbsp;&amp;nbsp;constructor:(name) -&amp;gt; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@name = name&lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Вместо этого можно использовать привязку через @. Coffeescript - единственный язык известных мне языков, который позволяет так делать. 
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&lt;/code&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;class Person&lt;br /&gt;
&amp;nbsp;&amp;nbsp;constructor:(@name) -&amp;gt; &lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Методы класса / статические методы&amp;nbsp;&lt;/h3&gt;
Псевдоним&amp;nbsp;@ позволяет определять статические методы класса. &lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;class Number&lt;br /&gt;
&amp;nbsp;&amp;nbsp;@random: -&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return 4  # chosen by fair dice roll &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;# guaranteed to be random&lt;br /&gt;&lt;br /&gt;
               
alert Number.random()&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
Алгоритм генерации случайных чисел взят с &lt;a href=&quot;http://xkcd.com/221/&quot; target=&quot;_blank&quot;&gt;XKCD&lt;/a&gt;.
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/05/10-coffescript.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgG3Ix0TbSz9V2TVdDJCppioXbheWcGotFaoBcoSCQ8cRix05DYUeLUX2G4lqjAD2xehCn7M0vzKuT_-3pAzhpi3E2F3j8dCPXuXZA84mXG5ehp-6tyCTlsO0RG-5GKTfK0Ekr0aCTJnOw/s72-c/a_8467231b.jpg" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-3047214150980082767</guid><pubDate>Wed, 08 May 2013 10:35:00 +0000</pubDate><atom:updated>2013-05-15T11:01:07.290+03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">atdd</category><category domain="http://www.blogger.com/atom/ns#">bdd</category><category domain="http://www.blogger.com/atom/ns#">javas</category><category domain="http://www.blogger.com/atom/ns#">ORM</category><category domain="http://www.blogger.com/atom/ns#">php</category><category domain="http://www.blogger.com/atom/ns#">phpunit</category><category domain="http://www.blogger.com/atom/ns#">Silverlight</category><category domain="http://www.blogger.com/atom/ns#">tdd</category><category domain="http://www.blogger.com/atom/ns#">tddigest</category><category domain="http://www.blogger.com/atom/ns#">testing</category><category domain="http://www.blogger.com/atom/ns#">unit testing</category><category domain="http://www.blogger.com/atom/ns#">xunit</category><category domain="http://www.blogger.com/atom/ns#">ссылки</category><title>Сводка с фронтов от инфицированных тестами e01</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1NXz8fbC8Rh167rs3GAiA5o6CFdbPDD49oKrLUdVnKMr_adrJcLaaTT7HYNC23R83LvT_RVUDBFViWXyVMxm7EtHzxh3tOL-hf3TjXhwa6i5gngP4tMklEjC7FE4ThG5jNBd2nu6NqLw/s1600/TDD.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1NXz8fbC8Rh167rs3GAiA5o6CFdbPDD49oKrLUdVnKMr_adrJcLaaTT7HYNC23R83LvT_RVUDBFViWXyVMxm7EtHzxh3tOL-hf3TjXhwa6i5gngP4tMklEjC7FE4ThG5jNBd2nu6NqLw/s1600/TDD.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Открывает первую сводку с фронтов удараников TDD хвалебная статья-ода &quot;&lt;a href=&quot;http://agile.dzone.com/articles/not-using-test-first-youre&quot;&gt;Not Using Test-First? You&#39;re Doing it Wrong.&lt;/a&gt;&quot; Автор не просто рассказывает, почему TDD - это круто, а пытается объяснить, как  и чем улучшает test-first подход процесс разработки. #en #tdd&lt;br /&gt;
Продолжая тему полезности TDD &quot;&lt;a href=&quot;http://www.maltblue.com/software-development/testing/why-successful-software-includes-testing&quot; target=&quot;_blank&quot;&gt;Why Testing Makes a Project Successful and You Can’t Afford to Deny It&lt;/a&gt;&quot;. Автор развивает мысль о полезности 
тестирования, эпично приводя статистику расхода времени и денег на поиск
 и фикс багов:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
According to prweb.com, recent Cambridge University research found that, on average, software developers spend &lt;b&gt;50% of their programming time&lt;/b&gt; finding and fixing bugs and estimate that this costs the global economy &lt;b&gt;$312 billion per year&lt;/b&gt;.
&lt;/blockquote&gt;
Да уж, не кисло. Не будь частью этой статистики, пиши теты! #en&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Я всегда говорила, что 100% покрытие кода тестами - всего лишь круглое число, которое ничего не говорит о качестве тестов. Тестировать нужно правильно. &quot;&lt;a href=&quot;http://bellouti.wordpress.com/2012/10/17/100-code-coverage-might-not-be-enough/&quot; target=&quot;_blank&quot;&gt;100% code coverage might not be enough&lt;/a&gt;&quot;&amp;nbsp; - история как раз об этом. #en #tdd #100%&lt;br /&gt;
Отличный детализированный ответ на вопрос, &lt;a href=&quot;http://stackoverflow.com/questions/16396478/some-questions-on-mocking-ef-5-and-testing-repository-pattern&quot; target=&quot;_blank&quot;&gt;как мокать ORM и тестировать паттерн &quot;Репозиторий&quot;&lt;/a&gt; + код, как надо делать. #en&lt;br /&gt;
&quot;&lt;a href=&quot;http://engineeredweb.com/blog/2013/php-testing-private-and-protected-methods/&quot; target=&quot;_blank&quot;&gt;PHP: Testing Private and Protected Methods&lt;/a&gt;&quot; - статья из разряда &quot;запомни, как не надо делать&quot;: автор рассказывает, как можно тестировать приватные и защищённые методы класса с помощью рефлексии на php. #php #en На мой взгляд, возникновение необходимости тестировать закрытые методы класса - первый звоночек, что с кодом что-то не то. Приватные и защищённые методы для того и нужны, чтобы скрывать от посторонних глаз внутренние механизмы. &lt;a href=&quot;http://sergeyteplyakov.blogspot.com/2013/05/blog-post.html&quot;&gt;Сергей Тепляков подробно объясняет, почему тестировать закрытые методы классов - не лучшая идея&lt;/a&gt;. #ru &lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&quot;&lt;a href=&quot;http://www.littlehart.net/atthekeyboard/2013/04/30/testing-smells-try-catch/&quot; target=&quot;_blank&quot;&gt;Testing Smells - Try/catch&lt;/a&gt;&quot;- автор делится мыслями о тестах с душком, считая, что использовать try/catch в тестах - не уместно. И он прав. В тест-фреймворке должен быть предусмотрен механизм для тестирования ожидаемых исключений. Например, Assert.Throws&amp;lt;T&amp;gt;() в NUnit и xUnit .net или @expectedException или setExpectedException(), встроенные в PHPUnit, о котором идёт речь в статье. + пара рекомендаций от автора статьи касательно написания модульных тестов. #php #phpunit #en&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&quot;&lt;a href=&quot;http://www.requirementsmanagement.net/knowledge/linking-requirement-and-acceptance-tests/&quot; target=&quot;_blank&quot;&gt;Linking Requirement and Acceptance Tests&lt;/a&gt;&quot;- заметка о том, что приёмочные тесты и требования к системе не могут существовать друг без друга. Тесты как уточнения требований. Упавший тест показывает, какие требования не реализованы (реализованы некорректно), успешно прошедший тест подтверждает соответствие кода спецификациям. #atdd #bdd #en&lt;br /&gt;
Интересный видео-туториал &quot;&lt;a href=&quot;http://www.youtube.com/watch?feature=player_embedded&amp;amp;v=Lg0Dh87suoU&quot; target=&quot;_blank&quot;&gt;JavaScript Testing With Jasmine&lt;/a&gt;&quot; #en #video #javascript #jasmine&lt;br /&gt;
Видео доклада Noel Rappin &quot;Testing Should Be Fun&quot; с Ruby Conf&#39;12. Главный посыл - tdd превращает написание кода в своего рода игру, но есть некоторые фан-киллеры, например, медленные тесты, каша-тесты (hard to read tests). В докладе рассматривается, как &lt;strike&gt;спасти мир&lt;/strike&gt; вернуть фан от написания тестов. #en #video #ruby #tdd&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;object class=&quot;BLOGGER-youtube-video&quot; classid=&quot;clsid:D27CDB6E-AE6D-11cf-96B8-444553540000&quot; codebase=&quot;http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0&quot; data-thumbnail-src=&quot;http://img.youtube.com/vi/l07J_5luC3M/0.jpg&quot; height=&quot;360&quot; width=&quot;480&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://youtube.googleapis.com/v/l07J_5luC3M&amp;source=uds&quot; /&gt;&lt;param name=&quot;bgcolor&quot; value=&quot;#FFFFFF&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;embed width=&quot;480&quot; height=&quot;360&quot;  src=&quot;http://youtube.googleapis.com/v/l07J_5luC3M&amp;source=uds&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;
&lt;br /&gt;
И на закуску &lt;a href=&quot;http://www.radio-t.com/p/2013/05/04/podcast-339/&quot; target=&quot;_blank&quot;&gt;Радио-Т 339&lt;/a&gt; - очень интересная беседа получилась о TDD. Что же это всё-таки: единственно правильный путь или путь в никуда? #ru #podcast&lt;br /&gt;
&lt;h3&gt;
Инструментарий&lt;/h3&gt;
&lt;a href=&quot;http://extspec.codeplex.com/&quot; target=&quot;_blank&quot;&gt;Ext Spec&lt;/a&gt; - новая версия bdd-фреймворка для тестирования ext.js #bdd&lt;br /&gt;
&lt;a href=&quot;http://developer.yahoo.com/dotnet/silverlight/2.0/unittest.html&quot;&gt;Microsoft.Silverlight.Testing&lt;/a&gt; - Microsoft открыла фреймворк для unit-тестирования под Silverlight, используемый внутри компании. #en #silverlight &lt;br /&gt;
&lt;a href=&quot;http://www.jera.com/techinfo/jtns/jtn002.html&quot;&gt;MinUnit&lt;/a&gt; - минималистичный фреймворк для unit-тестирования на C&amp;nbsp; #c&lt;/div&gt;
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/05/e01.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1NXz8fbC8Rh167rs3GAiA5o6CFdbPDD49oKrLUdVnKMr_adrJcLaaTT7HYNC23R83LvT_RVUDBFViWXyVMxm7EtHzxh3tOL-hf3TjXhwa6i5gngP4tMklEjC7FE4ThG5jNBd2nu6NqLw/s72-c/TDD.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-3241051977448825774</guid><pubDate>Wed, 27 Feb 2013 03:37:00 +0000</pubDate><atom:updated>2013-02-27T07:58:02.239+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">php</category><category domain="http://www.blogger.com/atom/ns#">soap</category><category domain="http://www.blogger.com/atom/ns#">web services</category><title>love via soap II: php + c#</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;a href=&quot;http://sly-and-fluffy.blogspot.com/2012/02/asmx-php-love-via-soap-i.html&quot; target=&quot;_blank&quot;&gt;Часть 1, в которой рассказывалось, зачем это всё нужно, и как несложно реализуется взаимодействие&amp;nbsp; php-клиента с asmx-сервисом. &lt;/a&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
В этой части мы будем писать SOAP-сервис на php, а клиентскую часть - на C#.Так что пристегнись, это php! &lt;/div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;
Для построения SOAP-сервера в php есть класс &lt;a href=&quot;http://www.php.net/manual/en/class.soapserver.php&quot; target=&quot;_blank&quot;&gt;SoapServer&lt;/a&gt;, который поддерживает протоколы SOAP 1.1 и SOAP 1.2. Что он не поддерживает - так это автоматическую генерацию WSDL-документа для сервиса, который необходим для коммуникации между клиентом и сервером. Помните, как VS заботливо генерировала его для нас? Но это php. Тут есть несколько путей:&lt;/div&gt;
1. Создавать wsdl ручками&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
2. Использовать сторонние библиотеки (&lt;a href=&quot;http://sourceforge.net/projects/nusoap/&quot; target=&quot;_blank&quot;&gt;NuSOAP&lt;/a&gt;, PEAR::SOAP, &lt;a href=&quot;http://www.jool.nl/jool-tech-zone/webservice-helper/&quot; target=&quot;_blank&quot;&gt;WSHelper&lt;/a&gt;) или встроенные в используемый фреймворк хелперы (например, Zend_Soap_Server из Zend Framework), сильно облегчающие жизнь.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Понятно, что первый путь - для совсем уж крепких духом ребят. Во втором случае рутинная работа будет сделана (и генерация wsdl-документа) за нас. Останется только добавить классы, представляющие сервисы, и всё. Очень советую идти этим путём: сэкономите много сил и времени.&lt;br /&gt;
Пример сервиса, написанного с использованием библиотеки WSHelper. &lt;br /&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;/* service.php */ &lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;require_once &quot;config.php&quot;;&lt;br /&gt;require_once &quot;common.php&quot;;&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;if (isset($_SERVER[&#39;PHP_AUTH_USER&#39;]) &amp;amp;&amp;amp; isset($_SERVER[&#39;PHP_AUTH_PW&#39;]) &amp;amp;&amp;amp;&amp;nbsp;&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;/* тут код авторизации */&lt;/code&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;require_once &quot;classes/compress.class.php&quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; compress_start();&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $sesrvice_name = &lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;$_GET[&#39;class&#39;];&lt;/code&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // старт SOAP-сервера&lt;/code&gt;&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $WSHelper = new WSHelper(WSURI, $cache_dir, $service_name);&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Обработка запроса&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;$WSHelper-&amp;gt;handle();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;compress_out();&amp;nbsp;&amp;nbsp; &lt;br /&gt;}&lt;br /&gt;else&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;header(&quot;WWW-Authenticate: Basic realm=\&quot;Webservice\&quot;&quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;header(&quot;HTTP/1.0 401 Unauthorized&quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; die(&quot;No access!&quot;);&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;}&amp;nbsp;&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;/* updateservice.php */&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;class updateservice {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; * Gets the latest version for specified version&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; * @param string[]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; * @return release[]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public function GetLastVersionForModule($modules)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $updates = array();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $query = &quot;SELECT * FROM `releases` WHERE `IsPublic`=1 AND `ModuleID` IN (&quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach($modules as $key=&amp;gt;$moduleID)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $query.= &quot;&#39;&quot; . htmlspecialchars($moduleID) . &quot;&#39;, &quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $query = substr($query, 0, strlen($query)-2) .&quot;)&quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $result = DB::GetConnection()-&amp;gt;query($query);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($result != FALSE AND $result-&amp;gt;num_rows&amp;gt;0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while ($row = $result-&amp;gt;fetch_object()) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $updates[] = $row;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $updates;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;} &lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Что тут происходит? Клиент отправляет запрос по адресу &lt;i&gt;http://somehost/service.php?class=updateservice&amp;amp;wsdl&lt;/i&gt;. Get-параметр &lt;i&gt;class&lt;/i&gt; - это как раз имя класса, который будет обрабатывать запрос.&amp;nbsp; В скрипте service.php после проверки авторизации запускается обёртка WSHelper поверх стандартного SOAP-сервера и обрабатывается запрос.&amp;nbsp; Для того, чтобы был сгенерирован правильный wsdl-документ, метод класса, представляющего сервис, должен иметь определённые типы входных параметров (&lt;b&gt;@param&lt;/b&gt;) и возвращаемого значения (&lt;b&gt;@return&lt;/b&gt;). Спецификации делаются в виде phpdoc-комментариев перед именем метода. В примере на вход сервису нужен массив строк, а возращается массив объектов типа release. Пользовательские типы данных тоже должны быть строго специфицированые.&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
//Класс release&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;class release {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /** @var string */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public $ModuleID;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /** @var string */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public $Version;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /** @var string */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public $Date;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /** @var string */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public $Description;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;}&lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
Типы данных описываются в отдельной секции&amp;nbsp; wsdl-документа.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq_iEUWcgmyZSAe75DedUOO1V0X-RS_mSsFwJ77jci6YINYvX5IRwvY11FoewZK2tbkWWJ5Cq_-xpgxBbcUyJ3rX5mIvqHwUeZPyMl4BFbyz2mslJS8LQU2fT0gUsW57FHw_iU-siHIJ0/s1600/types.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq_iEUWcgmyZSAe75DedUOO1V0X-RS_mSsFwJ77jci6YINYvX5IRwvY11FoewZK2tbkWWJ5Cq_-xpgxBbcUyJ3rX5mIvqHwUeZPyMl4BFbyz2mslJS8LQU2fT0gUsW57FHw_iU-siHIJ0/s1600/types.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Клиент из .Net может взаимодействовать с SOAP-сервисом через супер-мощную встроенную библиотеку WCF. Для этого в VS-проекте нужно лишь добавить ссылку на сервис (Add service reference):&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT2OMtJq7Yna6MQd8q54jfEY48GGHuaL2hhxQGjtKBLcBZoThWJnIhU3hgn2m30zyotWUg31w5zEF8EgZ73fIQmX2igSqeSEFMQw7I5RCDgncMGc7bJlC22d2Nxd5V27y2w1eEVgXwYlE/s1600/service.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT2OMtJq7Yna6MQd8q54jfEY48GGHuaL2hhxQGjtKBLcBZoThWJnIhU3hgn2m30zyotWUg31w5zEF8EgZ73fIQmX2igSqeSEFMQw7I5RCDgncMGc7bJlC22d2Nxd5V27y2w1eEVgXwYlE/s640/service.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Важно нажать на кнопку Advanced в левом нижнем углу окошка &quot;Add Service Reference&quot; и поставить галочку &quot;Allow generation of asynchronous operations&quot; в появившемся окне. Этим мы скажем Visual Studio сгенерировать асинхронные вызовы методов веб-сервиса. &lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Теперь можно обращаться к сервису из десктоп-приложения или из другого сервиса на C#. В примере ниже клиент проверяет наличие новых версий програмных модулей на сервере через async-запрос к Soap-сервису.&lt;/div&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
var updateserv = new updateservicePortTypeClient();&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;br /&gt;    
//настройки аутентификации для работы с сервисом&lt;br /&gt;
updateserv.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;&lt;br /&gt;
updateserv.ClientCredentials.Windows.AllowNtlm = false;&lt;br /&gt;            
updateserv.ClientCredentials.UserName.UserName = settings.Email;&lt;br /&gt;
updateserv.ClientCredentials.UserName.Password = settings.UserID;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;br /&gt;
//подписываемся на обработку события по окончанию получения данных от сервиса
updateserv.GetLastVersionForModuleCompleted += updateserv_GetLastVersionForModuleCompleted;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;br /&gt;
//открываем соединение&lt;br /&gt;
updateserv.Open();&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;br /&gt;
//вызываем метод веб-сервиса &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;updateserv.GetLastVersionForModuleAsync(modules);&lt;br /&gt;
/*....*/&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;br /&gt;
void updateserv_GetLastVersionForModuleCompleted(object sender, GetLastVersionForModuleCompletedEventArgs e)&lt;br /&gt;
{&lt;br /&gt;
//если всё прошло без ошибок, супер!&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;if (e.Error == null)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //делаем что-то с полученными данными&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;br /&gt;
//обработка ошибок&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;

&lt;br /&gt;
&lt;h3 style=&quot;font-weight: bold; text-align: left;&quot;&gt;
Пара слов об авторизации&lt;/h3&gt;
Очень удобно было использовать в сервисах&amp;nbsp; basic HTTP аутентификацию PHP:&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;if (!isset($_SERVER[&#39;PHP_AUTH_USER&#39;]) &amp;amp;&amp;amp; !isset($_SERVER[&#39;PHP_AUTH_PW&#39;]))&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; Header(&quot;WWW-Authenticate: Basic realm=\&quot;My realm\&quot;&quot;);&lt;br /&gt;&amp;nbsp; Header(&quot;HTTP/1.0 401 Unauthorized&quot;);&amp;nbsp; &lt;br /&gt;&amp;nbsp; exit;&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Но&amp;nbsp;оказалось, что в Apache, когда php стоит как FastCGI, такой подход не работает: не установлены переменные PHP_AUTH_USER и PHP_AUTH_PW. Есть хак, решающий эту проблему.&lt;/div&gt;
В .httaccess добавить&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
&amp;lt;IfModule mod_rewrite.c&amp;gt;&lt;br /&gt;
RewriteEngine On&lt;br /&gt;
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]&lt;br /&gt;
&amp;lt;/IfModule&amp;gt;&lt;br /&gt;
&lt;/code&gt;
Перед кодом авторизации вставить следующий код:&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
list($_SERVER[&#39;PHP_AUTH_USER&#39;], $_SERVER[&#39;PHP_AUTH_PW&#39;]) = explode(&#39;:&#39;, base64_decode(substr($_SERVER[&#39;HTTP_AUTHORIZATION&#39;], 6)));&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&lt;/code&gt; &lt;br /&gt;
Всё, после этого базовая авторизация должна снова работать.&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Если никак не помогает, можно с клиента посылать Soap-серверу аутентификационные данные в заголовке Soap-сообщения. Распарсить заголовок на сервере - это уже дело техники.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Как это выглядит на клиенте.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Добавляем дополнительный заголовок к вызову WCF-сервиса:&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;var updateserv = new updateservicePortTypeClient();&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;var channel = (IContextChannel)updateserv.InnerChannel;&lt;br /&gt;using(OperationContextScope scope = new OperationContextScope(channel))&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var securitytoken = Convert.ToBase64String(Encoding.UTF8.GetBytes(_token));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OperationContext.Current.OutgoingMessageHeaders.Add(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MessageHeader.CreateHeader(&quot;securitytoken&quot;, &quot;&quot;, securitytoken)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; updateserv.GetLastVersionForModuleAsync(modules);&lt;br /&gt;}&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Нужно учесть, что заголовок с аутентификационными данными нужно добавлять для всех вызовов Soap-сервисов. Чтобы не писать дополнительный код (если заголовок одинаковый во всех случаях), можно легко добавить custom header для WCF-вызовов через config-файл:&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
&amp;lt;endpoint address=&quot;http://.../service.php&quot; &amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;headers&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;securitytoken&amp;gt;abcdef12345%$#&amp;lt;/securitytoken&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;/headers&amp;gt;&lt;br /&gt;&amp;lt;/endpoint&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&lt;/code&gt; &lt;br /&gt;
Как это выглядит на сервере. &lt;br /&gt;
От клиента серверу в заголовке сообщения приходит что-то вроде:&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
&amp;lt;s:Header&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;securitytoken&amp;gt;1a232d4dg35&amp;lt;/securitytoken&amp;gt;&lt;br /&gt;&amp;lt;/s:Header&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
Заголовок легко парсится в нужные переменные, и код авторизации менять, по сути, не надо.&amp;nbsp; Если вы используете NuSOAP, то заголовок придется парсить вручную: не умеет NuSOAP разбирать SOAP:Header.&lt;br /&gt;
И напоследок. Чтобы хоть как-то облегчить свою участь, можно тестить сервисы с помощью &lt;a href=&quot;http://codeception.com/06-19-2012/testing-webservices.html&quot; target=&quot;_blank&quot;&gt;Codeception&lt;/a&gt;. &lt;/div&gt;
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/02/love-via-soap-ii-php-c.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq_iEUWcgmyZSAe75DedUOO1V0X-RS_mSsFwJ77jci6YINYvX5IRwvY11FoewZK2tbkWWJ5Cq_-xpgxBbcUyJ3rX5mIvqHwUeZPyMl4BFbyz2mslJS8LQU2fT0gUsW57FHw_iU-siHIJ0/s72-c/types.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-6187263888673763836</guid><pubDate>Tue, 12 Feb 2013 17:17:00 +0000</pubDate><atom:updated>2013-02-13T06:19:39.273+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">massive</category><category domain="http://www.blogger.com/atom/ns#">micro orm</category><category domain="http://www.blogger.com/atom/ns#">ms sql ce</category><title>Микромир ORM на примере Massive</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
В мире больших и тяжеловесных ORM-решений, таких как NHibernate и Entity Framework, вполне предсказуемым стало появление течения микро-ORM: легковесных прослоек между БД и объектами приложения. Чем хороши microORM? Прежде всего, скоростью выполнения запросов: она сопоставима со скоростью чистых запросов через SqlDataReader. Потом - микро размерами: например, Massive - это всего лишь один подключаемый файл на 673 строки кода, в отличие от NHibernate или EF, которые тянут за собой целую dll-ку на несколько сот килобайт.&amp;nbsp; Наиболее известные из micro ORM:&lt;/div&gt;
1) &lt;a href=&quot;http://code.google.com/p/dapper-dot-net/&quot; target=&quot;_blank&quot;&gt;Dapper&lt;/a&gt;, разработанный и активно использующийся в &lt;a href=&quot;http://stackoverflow.com/&quot; target=&quot;_blank&quot;&gt;StackOverflow&lt;/a&gt; и &lt;a href=&quot;http://stackexchange.com/&quot; target=&quot;_blank&quot;&gt;StackExchange&lt;/a&gt;&lt;br /&gt;
2) &lt;a href=&quot;https://github.com/robconery/massive&quot; target=&quot;_blank&quot;&gt;Massive&lt;/a&gt;, разработанный Rob Conery, пример использования - &lt;a href=&quot;http://hanselminutes.com/&quot; target=&quot;_blank&quot;&gt;HanselMinutes&lt;/a&gt;&lt;br /&gt;
3) PetaPOCO&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Massive - это лучше, чем шоколад&lt;/h3&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Основа Massive - это dynamic-типы, появившиеся в .NET 4.0. Чтобы понять, что такое Massive, как и зачем он появился на свет, посмотриет видео&amp;nbsp; &lt;a href=&quot;http://sly-and-fluffy.blogspot.com/2011/10/to-orm-or-not-to-orm.html&quot; target=&quot;_blank&quot;&gt;&quot;Kill your ORM&quot;&lt;/a&gt; с выступления Роба Конери на NDC 2011. А чтобы понять, насколько Massive лучше шоколада,&amp;nbsp; давайте напишем небольшое тестовое приложение, выводящее план счетов из БД в сгруппированом виде.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
БД - MS SQL CE 3.5. Структура базы:&lt;/div&gt;
&lt;code class=&quot;prettycode&quot;&gt;
//таблица групп&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;CREATE TABLE [_accountGroups]&lt;br /&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp; [AccountGroupId] INT NOT NULL IDENTITY (1,1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; [GroupName] NVARCHAR(100) NOT NULL DEFAULT N&#39;&#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp; [ParentGroupId] INT,&lt;br /&gt;&amp;nbsp;&amp;nbsp; [GroupNum] INT NOT NULL DEFAULT0&lt;br /&gt;);&lt;br /&gt;//таблица счетов&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;CREATE TABLE [_accounts]&lt;br /&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp; [AccountId] INT NOT NULL IDENTITY (1,1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; [AccountName] NVARCHAR(250) NOT NULL DEFAULT N&#39;&#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp; [AccountNum] INT NOT NULL DEFAULT0,&lt;br /&gt;&amp;nbsp;&amp;nbsp; [GroupId] INT NOT NULL,&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; [ActualSaldo] MONEY NOT NULL DEFAULT0&amp;nbsp;&amp;nbsp; &lt;br /&gt;);&amp;nbsp;&lt;/code&gt;
&lt;br /&gt;
Группы счетов могут содержать подгруппы. Каждый счет имеет определённую группу.&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Теперь нужно добавить Massive в проект, взяв с &lt;a href=&quot;https://github.com/robconery/massive&quot; target=&quot;_blank&quot;&gt;github&lt;/a&gt; последнюю версию. На github-е можно найти разные версии Massive для работы с разными СУБД: PostgreSql, Oracle, Sqlite. Нам нужен стандарный Massive.cs.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;h4 style=&quot;font-weight: bold;&quot;&gt;
Как отобразить таблицу БД на объект приложения с помощью Massive?&amp;nbsp;&lt;/h4&gt;
В Massive за это отвечает класс DynamicModel. Есть два способа получения данных из таблиц:&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
1) создание класса таблицы, наследующего DynamicModel (который используется в тестовом приложении):&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public class Accounts : DynamicModel&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Accounts()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : base(&quot;ChartOfAccount&quot;, &quot;_accounts&quot;, &quot;AccountId&quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class Groups : DynamicModel&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Groups()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : base(&quot;ChartOfAccount&quot;, &quot;_accountGroups&quot;, &quot;AccountGroupId&quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/code&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Первым параметром в базовом конструкторе указывается имя connection string (об этом чуть ниже), вторым - имя таблицы, третьим - первичный ключ таблицы. &lt;br /&gt;
2) inline-определение через DynamicModel &lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;pre&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accounts&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DynamicModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ChartOfAccount&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_accounts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;primaryKeyField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AccountId&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;h4 style=&quot;font-weight: bold;&quot;&gt;
Откуда Massive берёт connection string?&amp;nbsp;&lt;/h4&gt;
Massive смотрит в конфиг-файл приложения и ищет там секцию &amp;lt;connectionStrings&amp;gt;. Из всех вариантов выбирается тот, чьё имя указано в качестве первого параметра в конструкторе DynamicModel. В примере используется следующий app.config:&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&amp;gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;connectionStrings&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&quot;ChartOfAccount&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; connectionString=&quot;Data Source=demo.sdf;Password=blablabla;&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; providerName=&quot;System.Data.SqlServerCe.3.5&quot; /&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/connectionStrings&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;/code&gt;
&lt;br /&gt;
Заглянем на мгновение &quot;под капот&quot;. Что происходит в конструкторе DynamicModel:&lt;br /&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;
public DynamicModel(string connectionStringName, string tableName = &quot;&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string primaryKeyField = &quot;&quot;, string descriptorField = &quot;&quot;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* не интересно */&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var _providerName = &quot;System.Data.SqlClient&quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (ConfigurationManager.ConnectionStrings[connectionStringName].ProviderName != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; providerName = ConfigurationManager.ConnectionStrings[connectionStringName].ProviderName;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;_factory = DbProviderFactories.GetFactory(_providerName);&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;ConnectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;&lt;br /&gt;}
&lt;/code&gt;
&lt;/div&gt;
Тут интересен providerName,&amp;nbsp; по которому получается специфичная для СУБД DbProviderFactory. Если неправильно указать в конфиге providerName, можно получить исключение &quot;Unable to find the requested .Net Framework Data Provider. It may not be installed.&quot;. &lt;br /&gt;
Собственно говоря, теперь можно делать select/insert/update/delete запросы к базе. Но рано радоваться. Давайте осуществим поставленную задачу: выведем план счетов по группам. Выводить будем используя WinForm в TreeView. Ничего лишнего.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ6XBPNdxsjxY3IGecZkAKiWLE6UkZK4JOBIPDPHPbcDI32YceQ_l2aBE2uPV2iqtcHYNLa3DEICL3zYKtDrxNEqAIdZ825oGQO5HFZD3sNY3-zibFlQw_0qm_PGFq2G_po2IsI1Lx4l0/s1600/form.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;267&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ6XBPNdxsjxY3IGecZkAKiWLE6UkZK4JOBIPDPHPbcDI32YceQ_l2aBE2uPV2iqtcHYNLa3DEICL3zYKtDrxNEqAIdZ825oGQO5HFZD3sNY3-zibFlQw_0qm_PGFq2G_po2IsI1Lx4l0/s400/form.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h4 style=&quot;font-weight: bold;&quot;&gt;
Как сделать select в Massive?&amp;nbsp;&lt;/h4&gt;
Можно использовать преимущества DynamicModel, где есть&amp;nbsp; полезные методы на все случаи жизни (All(), Count(), Single() etc.) или ручками выполнять чистый sql через &lt;code class=&quot;prettycode&quot;&gt;Massive.DB.Current.Query();&lt;/code&gt;. Наш путь - это Dynamic Model. В методе All() есть несколько интуитивно-понятных параметров: &lt;b&gt;where&lt;/b&gt;, &lt;b&gt;orderBy&lt;/b&gt;, &lt;b&gt;limit&lt;/b&gt;, &lt;b&gt;columns&lt;/b&gt; (по умолчанию &lt;b&gt;*&lt;/b&gt;, что значит выбрать все столбцы), &lt;b&gt;args&lt;/b&gt; (массив аргументов для where). Всё просто и понятно.&lt;br /&gt;
Вернёмся к форме. На событие Load формы будем строить дерево плана счетов:&lt;br /&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;
private void Form1_Load(object sender, EventArgs e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LoadChartOfAccount();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; tvChartOfAccount.Nodes[0].Expand();&lt;br /&gt;}&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;private void LoadChartOfAccount()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var groups = new Groups();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var accounts = new Accounts();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var group in groups.All(orderBy: &quot;GroupNum&quot;))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TreeNode tn = new TreeNode(group.GroupName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tn.Name = group.AccountGroupId.ToString();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var account in accounts.All(where: &quot;GroupID=@0&quot;, args: new object[] { group.AccountGroupId }, orderBy: &quot;AccountNum&quot;))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tn.Nodes.Add(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; account.AccountNum.ToString() + &quot; &quot; +&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; account.AccountName + &quot; &quot; +&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; account.ActualSaldo.ToString()&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;TreeNode[] parentNode = tvChartOfAccount.Nodes.Find((group.ParentGroupId ?? &quot;root&quot;).ToString(), true);&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parentNode[0].Nodes.Add(tn);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;}&amp;nbsp;&lt;/code&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Результат:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYWWt3TcOSXx6lqgyYLtLiOEzifubqrBzCnN3uE6ognCF7kUDDEzROTC4CDUHGws1Rg2imqcfURDQ4IIN2K6zynprH5cj82snkRbxAyLDLwtkGE0yuvex40X9YFfp1sKVa-DoobwTfRig/s1600/form_run.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;246&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYWWt3TcOSXx6lqgyYLtLiOEzifubqrBzCnN3uE6ognCF7kUDDEzROTC4CDUHGws1Rg2imqcfURDQ4IIN2K6zynprH5cj82snkRbxAyLDLwtkGE0yuvex40X9YFfp1sKVa-DoobwTfRig/s400/form_run.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Вроде всё просто и понятно. Это если код не печатать, а использовать copy-paste :) А если печатать, то сразу же обнаружится печальная (в данном случае) особенность dynamic-типов: идентификация типов только на этапе исполнения. Это значит, что обращаясь к свойству dynamic-объекта, я могу написать что угодно, даже не существующее свойство (account.Blablabla), а исключение словлю только в момент выполенения кода, а не на этапе компиляции. &amp;nbsp; Это следует учитывать, работая с dynamic. Если в нашем примере опечататься и вместо &lt;code class=&quot;prettycode&quot;&gt;group.AccountGroupId &lt;/code&gt; написать &lt;code class=&quot;prettycode&quot;&gt;group.AccountGroupID&lt;/code&gt;, то можно обеспечить себе увлекательный поиск ошибки, т.к. Massive для имён полей объектов берёт названия столбцов таблицы как есть, поэтому регистр важен.&lt;br /&gt;
Если мы добавим немного функционала к приложению, например, поиск счета по номеру или названию, вскроется ещё один недостаток: подверженность slq-injection. Можно возразить, что это забота программиста, но вспоминая старый добрый Linq2Sql, о таком думать даже не приходилось. В Massive можно написать&amp;nbsp; &lt;code class=&quot;prettycode&quot;&gt;accounts.All(where: &quot;AccountNum LIKE &#39;@0&#39; OR AccountName LIKE &#39;@0&#39;&quot;, args: new object[] { filter } )&lt;/code&gt; или &lt;code class=&quot;prettycode&quot;&gt;accounts.All(where: &quot;AccountName LIKE &#39;&quot;+filter+&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&quot;&lt;/code&gt;&#39; OR AccountNum LIKE &#39;&quot;+filter+&quot;&#39;)&lt;/code&gt; со всеми вытекающими последствиями. Понятно, что в полноценных ORM, так же позволяющих выполнять чистый sql, тоже можно написать такого странного кода, но всё же там неподготовленный пользователь максимально ограничен от соприкосновения с чистым sql. В micro ORM пользователь находится в пограничном состоянии: вроде и не чистый sql, но и не объекты. &lt;br /&gt;
&lt;h3&gt;
Заключение&lt;/h3&gt;
Есть такое мнение:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-EZf3-seszuVoYs7VTYz2bCFK4G48cP0T8P72Iv8Z-JCBy9ySD-3vio_K5mUv6GiQvIV8dqt9BgO6DGcyI4fHEDRzIZjAI9xRGC7NhIEsORvIrpFhBmQfWrj1S6zrs_Bbls-zYUZ86yk/s1600/not+orm.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-EZf3-seszuVoYs7VTYz2bCFK4G48cP0T8P72Iv8Z-JCBy9ySD-3vio_K5mUv6GiQvIV8dqt9BgO6DGcyI4fHEDRzIZjAI9xRGC7NhIEsORvIrpFhBmQfWrj1S6zrs_Bbls-zYUZ86yk/s1600/not+orm.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
и оно имеет право на жизнь. Хоть Massive возвращает объект, представляющий строку таблицы, но делает это особым образом: тип объекта (а соответственно, все его поля) становятся изветсны только во время исполнения кода, что имеет свои недостатки. Зато плюс - нет никаких огромных конфиг-файлов с описаниями объектов и связей между ними - не нужно создавать заново схему данных каждый раз, когда структура базы меняется (да, EF code-first - это круто). Нет отслеживания данных, вобще никаких фич, кроме select/update/insert/delete. Минималистично и быстро. Massive делает много рутинной работы: все эти датаридер, команды, параметры... - всё это скрыто в DynamicModel. &lt;br /&gt;
Стоит или не стоит использовать micro-ORM? Можно долго рассуждать на эту
 тему, разводить руками, пожимать плечами. В конечном итоге, это зависит от нужд проекта.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/02/orm-massive.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ6XBPNdxsjxY3IGecZkAKiWLE6UkZK4JOBIPDPHPbcDI32YceQ_l2aBE2uPV2iqtcHYNLa3DEICL3zYKtDrxNEqAIdZ825oGQO5HFZD3sNY3-zibFlQw_0qm_PGFq2G_po2IsI1Lx4l0/s72-c/form.jpg" height="72" width="72"/><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-9200832489791621706</guid><pubDate>Fri, 08 Feb 2013 16:24:00 +0000</pubDate><atom:updated>2013-02-11T06:12:35.496+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">angular.js</category><category domain="http://www.blogger.com/atom/ns#">backbone.js</category><category domain="http://www.blogger.com/atom/ns#">batman.js</category><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">jquery</category><category domain="http://www.blogger.com/atom/ns#">knockout.js</category><category domain="http://www.blogger.com/atom/ns#">mvc framework</category><title>3 js-фреймворка на личном опыте</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Разрабатывая веб-приложение (не путать с веб-сайтом с интерактивным UI) на jQuery, Zepto или другом UI-ном фреймворке, довольно быстро приходишь к изобретению MV*-велосипеда, сначала&amp;nbsp; отделяя данные от UI-части приложения, а потом назначая ответственного за взаимодействием между ними. Резонный вопрос: а какие существуют готовые решения, облегчающие взаимодействие UI, данных и логики, поверх jQuery (Zepto)? И как ответ недавно мне попалась статья &quot;&lt;a href=&quot;http://www.designyourway.net/blog/resources/a-collection-of-javascript-mvc-framworks-that-you-should-know/&quot; target=&quot;_blank&quot;&gt;A Collection Of Javascript MVC Frameworks That You Should Know About&lt;/a&gt;&quot;. Знаете, сколько там фреймворков? Больше 30! Как же сделать правильный выбор? Выбор фреймворка - это серьезное решение, от которого не последним 
образом зависит будущее проекта. На решение каких проблем большим 
образом ориентирован фреймворк? Какой из MV* подходов используется во 
фреймворке (и стоит ли на этом заморачиваться)? Сильно ли тяжеловесен 
фреймворк? Сколько дополнительных библиотек он тянет за собой? Насколько
 быстро и легко разобраться с устройством фреймворка? Насколько хороша 
документация? Есть ли дружное сообщество вокруг библиотеки? Как не ошибиться, ведь все фреймворки похожи друг на друга, и каждый обещает сделать всю работу за меня? Да никак. Есть лишь несколько подсказок и советов от умудрённых опытом людей и сделанные на основе собственного опыта выводы. &lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;h3&gt;
Знакомство 1&lt;/h3&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFFAro3Ll7n3W7xa0YdbT5mFwyjsmZ_hjBOQx7mWRJJNI9oVQGzLkxmvZutALqh-vcs4aePbMo7yaPPsdVep3CtMNY5GlKuMOjaKN1O4tp6V8Yef7NrIpXbimkv3ABSyloNSABVAJuJoQ/s1600/backbone.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFFAro3Ll7n3W7xa0YdbT5mFwyjsmZ_hjBOQx7mWRJJNI9oVQGzLkxmvZutALqh-vcs4aePbMo7yaPPsdVep3CtMNY5GlKuMOjaKN1O4tp6V8Yef7NrIpXbimkv3ABSyloNSABVAJuJoQ/s200/backbone.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Первый, с кем я познакомилась из фреймворков, был &lt;a href=&quot;http://backbone.js/&quot;&gt;Backbone.js&lt;/a&gt;. Backbone.js может похвастаться &lt;a href=&quot;https://github.com/documentcloud/backbone/wiki/Projects-and-Companies-using-Backbone&quot; target=&quot;_blank&quot;&gt;внушительным списоком&lt;/a&gt; приложений, использующих фреймворк, и&amp;nbsp; кучей примочек вроде &lt;a href=&quot;http://backbone.marionette/&quot;&gt;Backbone.Marionette&lt;/a&gt;, &lt;a href=&quot;http://backbone.viewmaster/&quot;&gt;Backbone.ViewMaster&lt;/a&gt; и &lt;a href=&quot;https://github.com/nytimes/backbone.stickit&quot; target=&quot;_blank&quot;&gt;Backbone.stickit&lt;/a&gt;. Хотя такие примочки являются своего рода знаком, что какие-то вещи фреймворк не решает или решает плохо. В упакованном виде Backbone.js весит всего 6.3Кб,&amp;nbsp; а единственная жесткая зависимость - это &lt;a href=&quot;http://documentcloud.github.com/underscore/&quot;&gt;Underscore.js&lt;/a&gt;. Но если хочется использовать всю мощь Backbone.Router и иметь возможность манипулировать с DOM в Backbone.View, то без json2.js и jQuery (или Zepto) не обойтись. Backbone сразу же поразил меня своим мощным Backbone.Router, моделями и коллекциями. Я была неопытная, впечатлительная, он был моим первым javascript mv*-фреймворком.&lt;br /&gt;
Я могла описать модель данных (Backbone.Model)&lt;code class=&quot;prettycode&quot;&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;//backbone.js&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;var FrameworkModel = Backbone.Model.extend({ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; defaults: {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;title&quot;: &quot;&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;url&quot;: &quot;&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;shortDescription&quot; : &quot;&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }); &lt;/code&gt;&lt;br /&gt;
сделать на её основе коллекцию &lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;//backbone.js&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;var FrameworkCollection = Backbone.Collection.extend({ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; model: FrameworkModel&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/code&gt;
&lt;br /&gt;
показать html-шаблон элемента (Backbone.View)&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;//backbone.js&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;var FrameworkView = Backbone.View.extend({&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tagName: &quot;div&quot;,&amp;nbsp; //тэг элемента&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; className: &quot;line&quot;, //css-класс для тэга&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; template: $(&quot;#itemTemplate&quot;).html(), //html шаблонного div&#39;a&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; render: function() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var templ = _.template(this.template);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.$el.html(templ(this.model.toJSON()));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;//html скелет&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&amp;lt;script id=&quot;itemTemplate&quot; type=&quot;text/template&quot;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;span id=&quot;title&quot;&amp;gt;&amp;lt;a href=&quot;&amp;lt;%= url %&amp;gt;&quot;&amp;gt;&amp;lt;%= title %&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&amp;nbsp;&lt;/code&gt;&lt;code&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&amp;lt;span id=&quot;description&quot;&amp;gt;&amp;lt;%= shortDescription %&amp;gt; &amp;lt;/span&amp;gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&lt;/code&gt;
&lt;br /&gt;
и легко получить отображение всей коллекции: &lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ-ktTHRRl8DpM4GLW9StXPOZhCelnVpH2-UkSVnf8BHpsudO-YHxC_9y7iwR4N2EO8WP-8ikP-PeGcb3J8VyCfy7xOr85VI6vnpjnv1rzK_aVQz0lS1zaRH0cwUQB79ZGHbS29fHwBxA/s1600/bb_list.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;230&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ-ktTHRRl8DpM4GLW9StXPOZhCelnVpH2-UkSVnf8BHpsudO-YHxC_9y7iwR4N2EO8WP-8ikP-PeGcb3J8VyCfy7xOr85VI6vnpjnv1rzK_aVQz0lS1zaRH0cwUQB79ZGHbS29fHwBxA/s400/bb_list.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
а, если немного поработать с представлением (FrameworkView), то можно отлавливать изменения данных в модели и на лету обновлять форму.&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;//backbone.js&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;var FrameworkView = Backbone.View.extend({&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*...*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; events: {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;dblclick span#description&quot; : &quot;edit&quot;, //метод влючает режим редактирования&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;keypress input#description&quot; : &quot;update&quot; //метод сохраняет результат&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; initialize: function()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;//подписываем на изменения в модели рендер представления&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.model.bind(&#39;change&#39;, this.render, this); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; render: function() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //рендер представления из модели&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; update: function(e){&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp; &lt;/code&gt;//обновление модели&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp; &lt;/code&gt;//метод save вызывает событие change, на которое подписан наш метод render&lt;/code&gt; &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;this.model.save({shortDescription: this.$(&#39;input#description&#39;).val() }); &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; edit: function() {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //режим редактирования&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/code&gt;
&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Знакомство 2 &lt;/h3&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5BZ5fYSsNJPcsGwH4ToOf3forBmKChAP_dqCnGgCfsnHw-BRQcfxDVGPKKcNZ3MEnNnb6qTD6CoqCM5e64jElb_1vccy_QWHajWjG19UGMV8E9KMq-erJRurcqVPt8pdbO6ZXYn7kuPo/s1600/180x140ximg.php,qsrc=,hwww.spidersoft.com.au,_wp-content,_uploads,_2012,_05,_knockout.jpg,aw=180,ah=140.pagespeed.ic.FxAY2Z1dA2.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5BZ5fYSsNJPcsGwH4ToOf3forBmKChAP_dqCnGgCfsnHw-BRQcfxDVGPKKcNZ3MEnNnb6qTD6CoqCM5e64jElb_1vccy_QWHajWjG19UGMV8E9KMq-erJRurcqVPt8pdbO6ZXYn7kuPo/s1600/180x140ximg.php,qsrc=,hwww.spidersoft.com.au,_wp-content,_uploads,_2012,_05,_knockout.jpg,aw=180,ah=140.pagespeed.ic.FxAY2Z1dA2.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Потом я познакомилась с Knockout.js. С ним было всё иначе: декларативное связывание, автоматический апдейт UI. Он не требовал от меня наследоваться от своих классов, а ненавязчиво предлагал свои observable и computed возможности. Это было одновременно элегантно и мощно. &lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;//knockout.js&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;//модель&amp;nbsp; &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;function FrameworkModel (_title, _url, _shortDescription) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var self = this;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.title = &lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;ko.observable(&lt;/code&gt;_title);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.url = &lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;ko.observable(&lt;/code&gt;_url);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.shortDescription = ko.observable(_shortDescription);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.isEditing = ko.observable(false);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.toogleEdit = function()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.isEditing(true);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.finishEdit = function()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.isEditing(false);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;//отображение&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;function FrameworkView () {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var self = this;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.newFramework = ko.observable(new FrameworkModel(&quot;&quot;, &quot;&quot;, &quot;&quot;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.frameworks = ko.observableArray([]);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.addFramework = function()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;self.frameworks.push(new FrameworkModel( self.newFramework.title,&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;self.newFramework.url,&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;self.newFramework.shortDescription));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.newFramework.title = &quot;&quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.newFramework.url = &quot;&quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.newFramework.shortDescription = &quot;&quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;//магия&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;ko.applyBindings(new FrameworkView()); &amp;nbsp;&lt;/code&gt;
&lt;br /&gt;
Knockout просто делал то, что я хотела. С ним было легко и просто, хоть и по-другому. В отличие от Backbone.js&amp;nbsp; он ограничивал возможность работы с html-элементами в js-представлении, вынося это всё в разметку. Например, вот шаблон для отображения объекта. &lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;//knockout.js&amp;nbsp;&lt;/code&gt;&lt;/code&gt; &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;lt;script id=&quot;itemTemplate&quot; type=&quot;text/html&quot;&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div class=&quot;line&quot; data-bind=&quot;css: {editable:isEditing}&quot;&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;span id=&quot;title&quot;&amp;gt;&amp;lt;a href=&quot;&quot; data-bind=&quot;text: title, href: url&quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;lt;span id=&quot;description&quot; data-bind=&quot;text: shortDescription(), click: toogleEdit&quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;/code&gt;&amp;lt;input id=&quot;description&quot; type=&quot;text&quot; value=&#39;&#39; data-bind=&quot;value: shortDescription, enterKey: finishEdit&quot; /&amp;gt;&lt;/code&gt;&lt;/div&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;
&lt;br /&gt;
Для того, чтобы отобразить список элементов, на Backbone.js нужно создать дополнительно отображение для коллекции элементов, и уже в нём в цилке отрендерить каждый объект.&lt;code class=&quot;prettycode&quot;&gt; &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;//backbone.js &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;var FrameworkCollectionView = Backbone.View.extend({&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; el: $(&quot;#list&quot;), //указываем элемент, в который будут помещаться отрендеренные объекты&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; initialize: function() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /*...*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.render();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; render: function() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.collection.each(function(item) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.renderItem(item);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }, this);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; renderItem: function(item) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var itemView = new FrameworkView({ model: item });&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.$el.append(itemView.render().el); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;/*...*/&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;}&amp;nbsp;&lt;/code&gt;
&lt;br /&gt;
На knockout.js всё, что мне необходимо сделать, это в html-разметке элементу, в котором я хочу видеть список, указать data-bind:&lt;br /&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;//knockout.js &lt;/code&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;lt;div data-bind=&quot;template: { name: &#39;itemTemplate&#39;, foreach: frameworks }&quot;&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;
&lt;/div&gt;
Т.е. js-код по минимуму завязан на html-разметку. И это здорово. Knockout.js помогает думать немного в другом стиле, забыть о привязке данных к разметке и работать над логикой. И это, опять-таки, здорово! Backbone.js оставлял полностью на меня задачу обновления изменённых данных в модели / представлении. С knockout.js об этом даже не приходилось задумываться. Он действительно решал одну из моих&amp;nbsp; проблем. 
&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Знакомство 3 &lt;/h3&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsE-MxE6vEOaMzGWaJ0EepEq5TKQT1-ERhWT0VlW07Xw9LFGaU_3dIAkOVj_qfSDWu1tM6t73l_VcY1nJ7bRZViYh5CCJUW6Svi8ZXmGQZc7bGl9pYbitSPNoH1R5ex6ZM11SjnLaseHM/s1600/AngularJS-Shield-large%5B1%5D.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsE-MxE6vEOaMzGWaJ0EepEq5TKQT1-ERhWT0VlW07Xw9LFGaU_3dIAkOVj_qfSDWu1tM6t73l_VcY1nJ7bRZViYh5CCJUW6Svi8ZXmGQZc7bGl9pYbitSPNoH1R5ex6ZM11SjnLaseHM/s200/AngularJS-Shield-large%5B1%5D.png&quot; width=&quot;188&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
А потом случился AngularJs. Фреймворк от Google. Я не знаю, что ещё добавить. Первое, что отличает его от двух предыдущих фреймворков - это туториал, в котором расказывается, как тестировать код, написанный под Angular.js с помощью Jasmin. Гугл не подвёл. &lt;br /&gt;
Мне нравится идея вложенных окружений (scope), которая является основой Angular.Js:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot; style=&quot;width: 320px;&quot;&gt;
a scope can be seen as the glue which allows the template, model and controller to work together. Angular uses scopes, along with the information contained in the template, data model, and controller, to keep models and views separate, but in sync.&amp;nbsp;&lt;/blockquote&gt;
&lt;div style=&quot;clear: both; height: 2px;&quot;&gt;
&lt;/div&gt;
И дальше - самое прекрасное: двусторонне связывание данных! &lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
Any changes made to the model are reflected in the view; any changes that occur in the view are reflected in the model.&lt;/blockquote&gt;
Следующее, чем прекрасен Angular.js - он много чего умеет из коробки. Например, легко делаются такие рутинные вещи, как фильтрация и сортировка.&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
//html&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div&amp;gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;/code&gt;&lt;/code&gt;Search: &amp;lt;input ng-model=&quot;query&quot; /&amp;gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&amp;lt;div ng-repeat=&quot;framework in frameworks&amp;nbsp; | filter:query&quot;&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* ... */&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&amp;lt;/div&amp;gt;&amp;nbsp;&lt;/code&gt;
&lt;br /&gt;
Вообще, с Angular.js ты пишешь код и только спустя какое-то время понимаешь, что кроме ангулара ничего больше из библиотек в проекте нет. Даже jQuery не подгружен! И это прекрасно. Но если нужно сделать какуют-то обычную вещь, например, отследить нажатие Enter в текстовом поле, то придется либо подключать angular-ui + jquery, либо писать свою директиву (на самом деле knockout этим тоже грешен):&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
//js&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;angular.module(&quot;frameworkApp&quot;, []).directive(&#39;onEnter&#39;, &lt;br /&gt;&amp;nbsp; function() {&lt;br /&gt;&amp;nbsp; return function( scope, elem, attrs ) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elem.bind(&#39;keyup&#39;, function(e) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (e.keyCode === 13)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; scope.$apply(attrs.onEnter);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;br /&gt;&amp;nbsp; };&lt;br /&gt;}); &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;//html&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;lt;input id=&quot;description&quot; type=&quot;text&quot; value=&#39;&#39; ng-model=&quot;framework.shortDescription&quot; on-enter=&quot;framework.finishEdit()&quot; /&amp;gt;&amp;nbsp;&lt;/code&gt;
&lt;/div&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Заключение&lt;/h3&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Хороший инструмент отличается от плохого решением поставленной проблемы и простотой. С этой стороны мне очень понравился AngularJS. Он немного сложнее, чем KnockoutJS, но большой проект я бы, не задумываясь, начала на Angular. Но для небольшого проекта я бы выбрала Batman.js, который не попал в этот обзор, но о котором я ещё расскажу.&amp;nbsp; Но нет ничего лучше для того, чтобы понять, насколько удобно работать с фреймворком,&amp;nbsp; чем взять и поработать с ни: например, написать с его помощью какое-нибудь несложное приложение. И на основе полученных эмоций в ходе разработки, выбрать понравившийся. Поняно, что с таким зоопарком всех фреймворков не перепробуешь - специально для этого был создан проект &lt;a href=&quot;http://todomvc.com/&quot; target=&quot;_blank&quot;&gt;TODO MVC&lt;/a&gt;, где собраны реализации todo-списка с помощью разных js-фреймворков. &lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
P.S. Несколько дней назад twitter пополнил ряды js-фреймфорков, выпустив свой собственный фреймворк &lt;a href=&quot;https://github.com/twitter/flight/blob/master/README.md&quot; target=&quot;_blank&quot;&gt;Flight&lt;/a&gt;, который, конечно же, совсем другой, но пытается решить всё те же проблемы.&lt;/div&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Ссылки &lt;/h3&gt;
&lt;a href=&quot;http://backbonejs.org/&quot; target=&quot;_blank&quot;&gt;http://backbonejs.org &lt;/a&gt;- оффициальный сайт backbone.js [en]&lt;br /&gt;
&lt;a href=&quot;http://backbonejs.ru/&quot; target=&quot;_blank&quot;&gt;http://backbonejs.ru&lt;/a&gt; - русскоязчная документация по backbone.js &lt;br /&gt;
http://knockoutjs.com - оффициальный сайт knockout.js [en]&lt;br /&gt;
&lt;a href=&quot;http://learn.knockoutjs.com/&quot; target=&quot;_blank&quot;&gt;http://learn.knockoutjs.com&lt;/a&gt; - прекрасный интерактивынй туториал по knockout.js&lt;br /&gt;
&lt;a href=&quot;http://kmalakoff.github.com/knockback/&quot;&gt;http://knockback.js&lt;/a&gt; - backbone.js и knockout.js в одном флаконе: объеденены сильные стороны обоих фреймворков в ещё один фреймворк. &lt;br /&gt;
&lt;a href=&quot;http://angularjs.org/&quot; target=&quot;_blank&quot;&gt;http://angularjs.org&lt;/a&gt; - официальная документация по angular.js&lt;br /&gt;
&lt;a href=&quot;http://egghead.io/&quot; target=&quot;_blank&quot;&gt;http://egghead.io/&lt;/a&gt; - видеокурс по angular.js &lt;br /&gt;
Отличный обзор JS-фреймворков на хабре (&lt;a href=&quot;http://habrahabr.ru/post/149594/obzor-frejmvorkov-JS-MVC-chast1/&quot; target=&quot;_blank&quot;&gt;часть 1&lt;/a&gt; и &lt;a href=&quot;http://habrahabr.ru/post/149872/&quot; target=&quot;_blank&quot;&gt;часть 2&lt;/a&gt;)&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/02/3-js.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFFAro3Ll7n3W7xa0YdbT5mFwyjsmZ_hjBOQx7mWRJJNI9oVQGzLkxmvZutALqh-vcs4aePbMo7yaPPsdVep3CtMNY5GlKuMOjaKN1O4tp6V8Yef7NrIpXbimkv3ABSyloNSABVAJuJoQ/s72-c/backbone.png" height="72" width="72"/><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-8775753101791551722</guid><pubDate>Fri, 01 Feb 2013 19:02:00 +0000</pubDate><atom:updated>2013-02-02T16:58:59.211+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">AMD</category><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">jquery</category><category domain="http://www.blogger.com/atom/ns#">require.js</category><title>Философия AMD, RequireJs и модульная разработка веб-приложений на JavaScript</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Разделяй и влавствуй - подход на все времена. Концепция модульного программирования не нова, и хорошо себя зарекомендовала. В мире разработки web-приложений на JavaScript существует подход &lt;a href=&quot;https://github.com/amdjs/amdjs-api/wiki/AMD&quot; target=&quot;_blank&quot;&gt;Asynchronous Module Definition&lt;/a&gt; или AMD, который&lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
specifies a mechanism for defining modules such that the module and its dependencies can be asynchronously loaded [&lt;a href=&quot;http://specifies a mechanism for defining modules such that the module and its dependencies can be asynchronously loaded&quot; target=&quot;_blank&quot;&gt;1&lt;/a&gt;]&lt;/blockquote&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
т.е. по сути определяет API, следуя которому можно реализовать асинхронную загрузку самих модулей и их зависимостей. Следуя этому подходу, непроизвольно создаешь более элегантные решения, но это всего лишь бонусный побочный эффект. Главное - уменьшается хаос js-кода, сложность разработки и поддержки приложения. Каждый модуль явно указывает свои зависимости и получает только их, работая изолированно, что означает минимум мусора глобальной области видимости.&lt;br /&gt;
Всё, что нужно, чтобы начать использовать AMD подход в проекте, - это 
загрузчик, который знает, что такое AMD-модуль, и умеет подгружать 
зависимости.&amp;nbsp; Итак, &lt;/div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;h3 style=&quot;font-weight: bold; text-align: left;&quot;&gt;
Require.js &lt;/h3&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4G6-s5zyMmbJODnSSDyG4HNRfpbKdINzOg9QsjbdT5cQFDfpZHMefF8-umff558HxgrOLPCaR63XPHnyCERoYWvoqEygC6Z-B1FS_1IpvtgRMQUOTKBR7PT8J1RIhmigGvoRwyJ6cjLQ/s1600/c84429419b35b18ac65ef1df5c43c506.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4G6-s5zyMmbJODnSSDyG4HNRfpbKdINzOg9QsjbdT5cQFDfpZHMefF8-umff558HxgrOLPCaR63XPHnyCERoYWvoqEygC6Z-B1FS_1IpvtgRMQUOTKBR7PT8J1RIhmigGvoRwyJ6cjLQ/s1600/c84429419b35b18ac65ef1df5c43c506.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Ключевым объектом в &lt;a href=&quot;http://requirejs.org/&quot; target=&quot;_blank&quot;&gt;Require.js&lt;/a&gt;, как и в AMD-философии в целом, является модуль. Опеределяется модуль с помощью функции &lt;b&gt;define&lt;/b&gt;:&amp;nbsp;&lt;/div&gt;
&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;define(&quot;&amp;lt;module_name&amp;gt;&quot;,
        [&lt;span class=&quot;string&quot;&gt;&quot;dependency1&quot;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;dependency2&lt;/span&gt;],
        &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(dependency1, dependency2)&lt;/span&gt; {&lt;/span&gt;            
       }
    );&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Метод, который идёт последний аргументом в списке,&amp;nbsp; - это фабрика, которая создает и возвращает сам модуль. Фабрика выполняется только после загрузки всех зависимостей, указанных во втором аргументе. Модули, указанные как зависимости, ищутся в той же папке, где находится и сам Require.Js (подробнее на теме загрузки модулей я останавлюсь ниже).&amp;nbsp; Ппервый аргумент - это имя модуля. Всё вроде просто. Значит, надо создать свой модуль в AMD-стиле! Выходя за рамки учебных простых примеров, создадим что-то более близкое к задачам из реальной жизни. Например, мне нужен объект, который умеет строить календарь на указанный месяц и год и отмечать в нём даты.&lt;/div&gt;
&lt;code class=&quot;prettycode&quot;&gt;//&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;zeitproject.calendar.js&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;define(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &#39;calendar&#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&#39;jquery&#39;],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function( $ ){&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function Calendar()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var self = this;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.builCalendar = function(month, year)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var body = &quot;&quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //неинтересные детали&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return body;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.markDays = function(days_array, css_class, calendar)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //неинтересные детали&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return new Calendar();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;);&lt;/code&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Из зависимостей - только jquery (ну куда без него!). Знак $ в параметрах функции-фабрики - конечно же, ссылка на jquery. Фабрика возвращает экземпляр класса Calendar, объявленного в внутри самой фабрики, что ограничивает область видимости класса. А куда и кому она возвращает объект? Туда, откуда кем-то была вызвана. А кем и когда она была вызвана? А вызвана она могла быть, когда модуль попал в чей-то список зависимостей, и Require.Js пытается подгрузить модуль. Продолжая пример, Calendar.js является одной из зависимостей в app.js:&lt;/div&gt;
&lt;code class=&quot;prettycode&quot;&gt;//app.js &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;require([&quot;jquery&quot;, &quot;calendar&quot;, &quot;tooltip&quot;], function($, calendar, tooltip) {&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;//init vars&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;//...//&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; calendar.builCalendar(month, year, $(&#39;.calendar&#39;));&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;calendar.markDays(days[i][0], days[i][1], $(&#39;.calendar&#39;));&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;tooltip.init();&lt;br /&gt;}); &lt;/code&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
app.js - это точка входа в наше приложение. В нём конфигурируется Require.Js и инициализируется логика приложения. Это тот единственнй javascript-файл, который подгружается через Require.Js в index.html. Путь к нему указывается в атрибуте &lt;b&gt;data-main&lt;/b&gt;:&lt;/div&gt;
&lt;code class=&quot;prettycode&quot;&gt;
&amp;lt;script data-main=&quot;/js/app&quot; src=&quot;/js/require-jquery.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;br /&gt;
Для краткости расширение .js можно не указывать. &lt;br /&gt;
Конечно, тут есть маленькая хитрость - в примере подгружается Require.Js сразу &lt;a href=&quot;http://requirejs.org/docs/jquery.html&quot; target=&quot;_blank&quot;&gt;в связке с jquery&lt;/a&gt;, поэтому не нужно отдельно подгружать jquery. &lt;br /&gt;
&lt;h3 style=&quot;font-weight: bold; text-align: left;&quot;&gt;
Ручная настройка&lt;/h3&gt;
Require.Js - гибкая легконастраиваемая штука. Например, нужно настроить загрузку AMD-модулей для такой структуры каталогов:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGxoY2i0c5qWedYZ0R1s5fWeRCtju9WRtMvbHtkkt2NC8BHmLmE66F2vdJ0mwvXN_NQv23t76oe0N16JdAxaTiD08HLvBeD2XpY9pG8NI1tiKzRHzW61nMv1iZNlrSPBVYi2sbM34arwo/s1600/folders.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGxoY2i0c5qWedYZ0R1s5fWeRCtju9WRtMvbHtkkt2NC8BHmLmE66F2vdJ0mwvXN_NQv23t76oe0N16JdAxaTiD08HLvBeD2XpY9pG8NI1tiKzRHzW61nMv1iZNlrSPBVYi2sbM34arwo/s1600/folders.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Для этого в app.js перед вызовом require() нужно сконфигурировать Require.Js.&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
require.config({&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; baseUrl: &quot;/js&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; paths: {&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;/code&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;calendar&quot; : &quot;zeitproject.calendar&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;jquery&quot;&amp;nbsp;&amp;nbsp; : &quot;require-jquery&quot;,&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;formatter&quot;: &quot;/utils/formatter&quot;,&lt;/code&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;tooltip&quot;&amp;nbsp; : &quot;/controls/zeitproject.tooltip&quot;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;tiptip&quot; &amp;nbsp; : &quot;/controls/jquery.tiptip.min&quot;&lt;/code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp; });&lt;/code&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Всё довольно интуитивно: baseUrl - корневая папка, относительно которой указываются все последующие пути. Дальше указывается имя AMD-модуля (имя мы указывали в методе define() первым аргументом во время определения модуля). А что, если нужно подгрузить не AMD-модуль, который добавляет в глобальное пространство имён переменные? По сути, таким модулем может быть любой jquery-плагин. Или, даже, фреймворк: тот же Backbone.js является AMD-несовместимым. Не переписывать же его под AMD-сигнатуру?! Для этого в конфиге есть специальный раздел &lt;b&gt;shim&lt;/b&gt; (наверно, имелось в виду &quot;shame, не AMD-модуль!&quot;):&lt;/div&gt;
&lt;code class=&quot;prettycode&quot;&gt;
require.config({&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; baseUrl: &quot;/js&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; paths: {&lt;br /&gt;/*...*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;tiptip&quot;&amp;nbsp; : &quot;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;/controls/&lt;/code&gt;jquery.tiptip.min&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;tooltip&quot; : &quot;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&lt;code class=&quot;prettycode&quot;&gt;/controls/&lt;/code&gt;zeitproject.tooltip&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; shim: {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &#39;tiptip&#39; : {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; deps: [&#39;jquery&#39;],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; exports: &#39;tiptip&#39;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; });&lt;/code&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
В shim-секции определяется, какие зависимости есть у не AMD-модуля и псевдоним, под которым его можно указывать в списке зависимостей AMD-модулей. &lt;/div&gt;
&lt;code class=&quot;prettycode&quot;&gt;//zeitproject.tooltip.js &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;define(&quot;tooltip&quot;, [&quot;jquery&quot;, &quot;tiptip&quot;], function($){&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;function Tooltip()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;/*..*/ &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;});&amp;nbsp;&lt;/code&gt; &lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Вот и всё. Модули изолированы друг от друга, и знают лишь о существовании тех, без которых не могут работать. Это позволяет держать под контролем зависимости и облегчает жизнь. Надеюсь, вы прониклись Require.js и AMD-подходом к разработке веб-приложений.&lt;br /&gt;
&lt;h4&gt;
Ссылки&lt;/h4&gt;
&lt;a href=&quot;http://requirejs.org/&quot; target=&quot;_blank&quot;&gt;http://requirejs.org&lt;/a&gt; официальный сайт require.js, отличная документация и примеры &lt;br /&gt;
&lt;a href=&quot;https://github.com/amdjs/amdjs-api/wiki/AMD&quot; target=&quot;_blank&quot;&gt;AMD&lt;/a&gt; - описание API&lt;/div&gt;
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/02/amd-requirejs-javascript.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4G6-s5zyMmbJODnSSDyG4HNRfpbKdINzOg9QsjbdT5cQFDfpZHMefF8-umff558HxgrOLPCaR63XPHnyCERoYWvoqEygC6Z-B1FS_1IpvtgRMQUOTKBR7PT8J1RIhmigGvoRwyJ6cjLQ/s72-c/c84429419b35b18ac65ef1df5c43c506.png" height="72" width="72"/><thr:total>14</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-2864832856842467703</guid><pubDate>Wed, 30 Jan 2013 03:15:00 +0000</pubDate><atom:updated>2013-01-30T05:15:15.218+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">knockout.js</category><title>Keypress event в Knockout.js</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Столкнулась с проблемой в knockout.js: в текстовом нужно было отследить нажание кнопки Enter. Делов-то: привязываем к событию keypress нужный метод, и в нём уже смотрим, какая клавиша была нажата:&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;//html &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;lt;div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;input type=&quot;text&quot; data-bind=&quot;value: someValue, event : { keypress = function(data, event) { handleKeyPress(data, event) } }&quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;span data-bind=&quot;text: someValue&quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;//view model&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;var ViewModel = function() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var self = this;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.someValue = ko.observable(&#39;&#39;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.handleKeyPress = function(data, event)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (event.keyCode == 13)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //сделать что-нибудь полезное&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;ko.applyBindings(new ViewModel());&amp;nbsp;&lt;/code&gt;
&lt;br /&gt;
Но не тут-то было! После таких манипуляций текстовое поле перестало реагировать на нажатия всех клавиш, кроме enter. Помогло создание своего специализированного binding-а:&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
ko.bindingHandlers.enterKey = {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; init: function(element, valueAccessor, allBindings, vm) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ko.utils.registerEventHandler(element, &quot;keyup&quot;, function(event) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (event.keyCode === 13) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ko.utils.triggerEvent(element, &quot;change&quot;); &lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;//set &quot;this&quot; to the data and also pass it as first arg, in case function has &quot;this&quot; bound&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&lt;/code&gt;&lt;code class=&quot;prettycode&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; valueAccessor().call(vm, vm); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;};&amp;nbsp;&lt;/code&gt;
&lt;br /&gt;
В html это отразится привязыванием на созданный байндинг нужного метода:&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;input type=&quot;text&quot; data-bind=&quot;value: someValue, enterKey: doSomething } }&quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;span data-bind=&quot;text: someValue&quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;br /&gt;
Спасибо &lt;a href=&quot;http://stackoverflow.com/questions/11628789/binding-keypress-event-on-knockoutjs-observable-not-populated&quot; target=&quot;_blank&quot;&gt;stackoverflow&lt;/a&gt;&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/01/keypress-event-knockoutjs.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-5804243343904103142</guid><pubDate>Sat, 26 Jan 2013 17:41:00 +0000</pubDate><atom:updated>2013-01-26T19:41:49.051+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">мысли в слух</category><title>Плохой программист</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Наверное, многим знакома ситуация, когда, взглянув на чей-то код, думаешь &quot;$%#... как можно так писать?!&quot; Тут даже рефакторить бесполезно! Выкинуть бы да переписать с нуля! А бывало ли так, что вы сами оказывались по ту сторону баррикад? Что кто-то смотрел на ваш код, и в глазах ревизора читался ужас :)?&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
А как вы сами относитесь к коду, написанному вами же, полгода, год, два года назад? Кажется ли применённый подход и найденное решение таким же правильным? Или как-то так?&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4nhDoH-26wc7oO_UNDF7cGBMWSLfLq9SJfzwFd-1uqGtoQLoCh9YRG6ZmnO0LS6r_qAwwyfrNqOpTQW_oyKstOb6INo99eviJHuriS7VIWh1nPVQdkNy0ZIfuRSAIAbYqBlgG_ClC6NE/s1600/bad_programmer-178963.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4nhDoH-26wc7oO_UNDF7cGBMWSLfLq9SJfzwFd-1uqGtoQLoCh9YRG6ZmnO0LS6r_qAwwyfrNqOpTQW_oyKstOb6INo99eviJHuriS7VIWh1nPVQdkNy0ZIfuRSAIAbYqBlgG_ClC6NE/s1600/bad_programmer-178963.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Лично я считаю такую реакцию вполне нормальной и, даже, правильной. &lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Полгода (не говоря уже о том, что целый год), - это большой отрезок 
времени. Это целых 182 дня = 4368 часа, из которых 2912 часа человек бодрствует (при расчете, что на сон уходит 8 часов). Достаточно ли 2912 часов, чтобы узнать хоть что-нибудь новое и полезное для себя?&lt;br /&gt;
&lt;br /&gt;
За полгода могут измениться взгляды на всё, ведь даже новое хобби или прочитанная книга (статья)&amp;nbsp; - 
это способ открыть для себя что-то новое. Знакомство с новой технологией или изучение другого языка программирования - это способ научиться мыслить иначе. Хотя...&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
Программист на Фортране может написать программу на Фортране на любом языке программирования. &lt;br /&gt;
&lt;a class=&quot;external text&quot; href=&quot;http://lib.ru/ANEKDOTY/non_pas.txt&quot; rel=&quot;nofollow&quot;&gt;Ed Post, 1983&lt;/a&gt;&lt;/blockquote&gt;
Поэтому осознание того, насколько вы плохой программист, - это явный признак того, что как профессионал вы сделали шаг вперёд, стали лучше. &lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
It is possible that you are a bad programmer. You&#39;ll never know until someone better sees it. &lt;br /&gt;
(c) Scott Hanselman&lt;/blockquote&gt;
И пусть этим someone better будете вы сами :)
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/01/blog-post.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4nhDoH-26wc7oO_UNDF7cGBMWSLfLq9SJfzwFd-1uqGtoQLoCh9YRG6ZmnO0LS6r_qAwwyfrNqOpTQW_oyKstOb6INo99eviJHuriS7VIWh1nPVQdkNy0ZIfuRSAIAbYqBlgG_ClC6NE/s72-c/bad_programmer-178963.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5342535388237643243.post-6987189170762751479</guid><pubDate>Fri, 04 Jan 2013 18:29:00 +0000</pubDate><atom:updated>2013-01-06T17:28:13.005+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">coffeescript</category><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">SublimeText 2</category><title>Компиляция CoffeeScript в JavaScript используя Sublime Text 2</title><description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhq2sM9igurn-wxW7LsCzuMgtecEw-vLwdkxFLfftpUfTSdKceJYzSAhCL_oZ_9Na8qf3F4fWQNkD9vLuNti_1HBCek68t1VEqeu-bSLjQ8CLXLbJY2oKicY6hdKSy4Yy8FLen6TLiSmZ8/s1600/preview.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhq2sM9igurn-wxW7LsCzuMgtecEw-vLwdkxFLfftpUfTSdKceJYzSAhCL_oZ_9Na8qf3F4fWQNkD9vLuNti_1HBCek68t1VEqeu-bSLjQ8CLXLbJY2oKicY6hdKSy4Yy8FLen6TLiSmZ8/s1600/preview.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
CoffeeScript - рафинированный JavaScript, который хочется писать ещё и ещё. Цель этой заметки рассмотреть, как писать и компилировать код на CoffeeScript в js, используя Sublime Text 2.&lt;/div&gt;
Весь процес можно разбить на два этапа:&lt;br /&gt;
1. Подготовительный этап - установка компилятора CoffeeScript&lt;br /&gt;
2. Установка плагина CoffeeScript под Sublime Text 2&lt;br /&gt;
И так, приступим.&amp;nbsp; &lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;
На первом этапе нужно установить компилятор CoffeeScript в JavaScript. Есть несколько способов (&lt;a href=&quot;http://stackoverflow.com/questions/2879401/how-can-i-compile-coffeescript-from-net&quot; target=&quot;_blank&quot;&gt;способ1&lt;/a&gt;, &lt;a href=&quot;http://jashkenas.github.com/coffee-script/#usage&quot; target=&quot;_blank&quot;&gt;способ2&lt;/a&gt;), самый простой - использовать nodejs. Для этого скачиваем и устанавливаем &lt;a href=&quot;http://nodejs.org/download/&quot; target=&quot;_blank&quot;&gt;nodejs&lt;/a&gt;. После установки проверяем системную переменную &lt;b&gt;PATH&lt;/b&gt; (должна быть &lt;b&gt;%AppData%/npm&lt;/b&gt;&quot;):&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX-y-ADDtUYvuunJOCWytAFBzs6obaikKQ6jZb2cdZVxvB5AT_06_B6pZ_6W9xxjps8KIanZS6vHCvtbjNFwBx9R_X5jvrxpws34PGjTGv60BnkUWdCDBTz3BpJoZkRzQgc7lwqelGO5o/s1600/enviroment_var.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX-y-ADDtUYvuunJOCWytAFBzs6obaikKQ6jZb2cdZVxvB5AT_06_B6pZ_6W9xxjps8KIanZS6vHCvtbjNFwBx9R_X5jvrxpws34PGjTGv60BnkUWdCDBTz3BpJoZkRzQgc7lwqelGO5o/s1600/enviroment_var.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Если такой переменной нет, то нужно создать её.&lt;br /&gt;
Дальше в коммандной строке:&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
cd %PROGRAMFILES%/nodejs&lt;br /&gt;
npm install coffee-script&lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4-GctAQKYnORfX23hpk_TJcbvY8ujB7ZzXSuvOIkKLgIq2eQtCTF3VWVI_ogjtvA-1D0TWaIC0jO6KMiTRIoHdOJgeiEpfya_pSN69-xWi2URFO7AnbtkRbJUXSOpwaKX4zHLvYnvC7Q/s1600/install.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4-GctAQKYnORfX23hpk_TJcbvY8ujB7ZzXSuvOIkKLgIq2eQtCTF3VWVI_ogjtvA-1D0TWaIC0jO6KMiTRIoHdOJgeiEpfya_pSN69-xWi2URFO7AnbtkRbJUXSOpwaKX4zHLvYnvC7Q/s1600/install.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Теперь нужно добавить в системную переменную &lt;b&gt;PATH&lt;/b&gt; значение &lt;b&gt;%ProgramFiles%\nodejs\node_modules\.bin&lt;/b&gt;. Конечное значение переменной должно содержать &lt;b&gt;%AppData%\npm\;%ProgramFiles%\nodejs\node_modules\.bin&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Если всё сделано правильно, то теперь из командной строки можно вызвать компилятор CoffeeScript командой &lt;b&gt;coffee&lt;/b&gt;.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi25xpBShClhHCT_GYMsMCo_p7-ne8p8BXkufeFyrnrSwzqwZi0jxiZUS-ZeBKsNHvaHpIlTl_5b77G5B8v-ubDcDWd2PYfyWCPhzRaW7UmmWh9Q-gtlGq-rZw3vFEx-QUSXiDQ5lz8nko/s1600/run.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi25xpBShClhHCT_GYMsMCo_p7-ne8p8BXkufeFyrnrSwzqwZi0jxiZUS-ZeBKsNHvaHpIlTl_5b77G5B8v-ubDcDWd2PYfyWCPhzRaW7UmmWh9Q-gtlGq-rZw3vFEx-QUSXiDQ5lz8nko/s1600/run.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
На этом подготовительный этап закончен. Дело осталось за малым - установить и сконфигурировать плагин под Sublime Text 2.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;b&gt;Сtrl + Shift + P -&amp;gt; Install Packages &lt;/b&gt; (если не понятно, что это, то &lt;a href=&quot;http://www.sly-and-fluffy.blogspot.com/2012/12/3-sumblime-text-javascript-jquery.html&quot; target=&quot;_blank&quot;&gt;тут написано&lt;/a&gt;, как установить Package Control) и есть два плагина: &lt;a href=&quot;http://xavura.github.com/CoffeeScript-Sublime-Plugin/&quot; target=&quot;_blank&quot;&gt;CoffeeScript&lt;/a&gt;  и &lt;a href=&quot;https://github.com/aponxi/sublime-better-coffeescript&quot; target=&quot;_blank&quot;&gt;Better CoffeeScript&lt;/a&gt;, который является форком от первого. После установки нужно перезагрузить Sublime Text 2.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Конфигурация обоих плагинов для Windows-платформы одинаковая:&lt;/div&gt;
1. в Sublime Text 2 выбираем Preferences -&amp;gt; Browse Packages&lt;br /&gt;
2.&amp;nbsp; находим папку с именем плагина&lt;br /&gt;
3. находим и открываем в папке файл &lt;i&gt;CoffeeScript.sublime-build&lt;/i&gt;&lt;br /&gt;
4. заменяем начальное значение&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;cmd&quot;: [&quot;cake&quot;, &quot;sbuild&quot;]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , &quot;path&quot;: &quot;/usr/local/bin:$PATH&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , &quot;selector&quot;: &quot;source.coffee&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , &quot;working_dir&quot;: &quot;$project_path&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , &quot;variants&quot;:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;name&quot;: &quot;Run&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;cmd&quot;: [&quot;coffee&quot;, &quot;$file&quot;]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;br /&gt;}&lt;/code&gt; &lt;br /&gt;
на&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;
{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;path&quot;: &quot;$HOME/bin:/usr/local/bin:$PATH&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;cmd&quot;: [&quot;coffee&quot;,&quot;-c&quot;,&quot;$file&quot;],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;file_regex&quot;: &quot;^(...*?):([0-9]*):?([0-9]*)&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;selector&quot;: &quot;source.coffee&quot;,&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;windows&quot;:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;cmd&quot;: [&quot;coffee.cmd&quot;,&quot;$file&quot;]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} &lt;/code&gt; &lt;br /&gt;
5. сохраняем файл.&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Теперь создаем тестовый test.coffee с содержимым&amp;nbsp;&lt;code class=&quot;prettycode&quot;&gt;console.log &quot;Hello, world!&quot;&lt;/code&gt;, сохраняемся и жмём &lt;b&gt;Ctrl+B&lt;/b&gt;. Если всё прошло успешно, то в области сообщений (messaging board) должна появиться фраза &quot;Hello, world!&quot; и время выплонения скрипта, а в папке, где расположен test.coffee должен появиться test.js - скомпилированный в javascript coffeescript.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPxTBg8vgTME1EP8zhEpFvQV25L8NT1QVDUl-lHS8lsld4OLR5Obgmlt5Jyf1I6qbOlPwxkuxMe4M_e50p_qaCcdlCRw4d0LpJSX0dcomCzkiOSY1xiyQj75es2nDBulPzkq2jSG2xAr8/s1600/script.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPxTBg8vgTME1EP8zhEpFvQV25L8NT1QVDUl-lHS8lsld4OLR5Obgmlt5Jyf1I6qbOlPwxkuxMe4M_e50p_qaCcdlCRw4d0LpJSX0dcomCzkiOSY1xiyQj75es2nDBulPzkq2jSG2xAr8/s1600/script.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
И на последок пару слов о параметрах командной строки. Добавляя в строку &lt;code class=&quot;prettycode&quot;&gt;&quot;cmd&quot;: [&quot;coffee.cmd&quot;,&quot;$file&quot;]&lt;/code&gt; разные флаги, можно управлять компилятором CoffeeScript. Несколько команд, которые могут пригодиться:&lt;br /&gt;
&lt;b&gt;-c&lt;/b&gt; (--compile) - скомпилировать&amp;nbsp; в JavaScript и сохранить как файл .js папке рядом с исходным .coffee-файлом, если не указан каталог&lt;br /&gt;
&lt;b&gt;-o&lt;/b&gt; (--output) - указать каталог для скомпилированных js-файлов&lt;br /&gt;
&lt;b&gt;-p&lt;/b&gt; (--print) - вывести скомпилированный код JavaScript в stdout&lt;br /&gt;
В итоге, фрагмент билд-конфигурации с дополнительными флагами должен выглядеть так:&lt;br /&gt;
&lt;code class=&quot;prettycode&quot;&gt;&quot;cmd&quot;: [&quot;coffee.cmd&quot;, &quot;-c&quot;, &quot;$file&quot;]&lt;/code&gt; &lt;/div&gt;
&lt;/div&gt;
</description><link>http://sly-and-fluffy.blogspot.com/2013/01/coffeescript-javascript-sublime-text-2.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhq2sM9igurn-wxW7LsCzuMgtecEw-vLwdkxFLfftpUfTSdKceJYzSAhCL_oZ_9Na8qf3F4fWQNkD9vLuNti_1HBCek68t1VEqeu-bSLjQ8CLXLbJY2oKicY6hdKSy4Yy8FLen6TLiSmZ8/s72-c/preview.png" height="72" width="72"/><thr:total>18</thr:total></item></channel></rss>