<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2enclosuresfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:media="http://search.yahoo.com/mrss/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Coding matters</title><link>http://codingmatters.blogspot.com/</link><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/blogspot/SvAh" /><description>"Business software doesn't have to be a bolted-together mess"</description><language>en</language><managingEditor>noreply@blogger.com (Dmitry Kandalov)</managingEditor><lastBuildDate>Sun, 29 Jan 2012 20:43:18 PST</lastBuildDate><generator>Blogger http://www.blogger.com</generator><openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">30</openSearch:totalResults><openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">1</openSearch:startIndex><openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">25</openSearch:itemsPerPage><feedburner:info uri="blogspot/svah" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><creativeCommons:license>http://creativecommons.org/licenses/by/2.0/</creativeCommons:license><item><title>MPS is simple</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/bYjfLuUZCLA/mps-is-simple.html</link><category>mps</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Mon, 10 May 2010 03:08:01 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-8799571119913275761</guid><description>&lt;p&gt;If you have ever seen or tried &lt;a href='http://www.jetbrains.com/mps'&gt;MPS&lt;/a&gt; and it didn&amp;#8217;t make a lot of sense, do not believe your first impression, because meta-programming in MPS is simple.&lt;/p&gt;&lt;p&gt;There are only two things you have to know to create something useful in &lt;a href='http://www.jetbrains.com/mps'&gt;MPS&lt;/a&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;editors and&lt;/li&gt;&lt;li&gt;generators.&lt;/li&gt;&lt;/ul&gt;&lt;h1 id='editors'&gt;Editors&lt;/h1&gt;&lt;p&gt;Editors is the way you interact with your language in MPS. The thing is that MPS doesn&amp;#8217;t edit text files. It works with &lt;a href='http://en.wikipedia.org/wiki/Abstract_syntax_tree'&gt;abstract syntax tree&lt;/a&gt;. When you edit a program in MPS, you edit AST. Here is AST for hello world program written in Java:&lt;/p&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S-e6f5CFqhI/AAAAAAAAAaw/i6Pc1SPxhok/s640/ast.jpg' border='1' /&gt;&lt;p&gt;To define a language you describe types of nodes that can be in your language AST. In MPS this is done with &lt;strong&gt;concepts&lt;/strong&gt; (they are green).&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S-e6ksJRbMI/AAAAAAAAAbA/jydyC-jD4r4/s200/concepts.jpg' border='1' /&gt;&lt;p&gt;In a way concepts are classes for AST nodes and AST nodes are instances of concepts.&lt;/p&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S-e6iMNurTI/AAAAAAAAAa4/XoTaSGc8Nbs/s400/concepts_are_classes.jpg' border='1' /&gt;&lt;p&gt;For each concept you define an &lt;strong&gt;editor&lt;/strong&gt;.&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S-e6mUV6qOI/AAAAAAAAAbI/rNffwFjbVP8/s400/editor.jpg' border='1' /&gt;&lt;p&gt;Editors allow you to edit and view AST nodes in a text-like form. In a way editors that you define for concepts are &amp;#8220;editor classes&amp;#8221; and the area in which you actually edit programs consists of &amp;#8220;editor instances&amp;#8221;.&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S-e6n95I9oI/AAAAAAAAAbQ/ALyNlL8KifI/s400/editors_are_classes.jpg' border='1' /&gt;&lt;p&gt;If you like &lt;a href='http://martinfowler.com/eaaDev/uiArchs.html'&gt;MVC pattern&lt;/a&gt; and its flavours, you can think about AST nodes as a model and editors as view and controller. You can read more about concepts &lt;a href='http://confluence.jetbrains.net/display/MPS/Basic+notions'&gt;here&lt;/a&gt; and &lt;a href='http://confluence.jetbrains.net/display/MPS/Structure'&gt;here&lt;/a&gt; and about editors &lt;a href='http://confluence.jetbrains.net/display/MPS/Editor'&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;h1 id='generators'&gt;Generators&lt;/h1&gt;&lt;p&gt;While having AST and being able to edit it is great, usually you would like to produce something useful like java code or text files. This is what &lt;em&gt;generators&lt;/em&gt; are for. They take AST and transform it into real files on your hard drive.&lt;/p&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S-fQD73RULI/AAAAAAAAAbY/xOi7yB2JMUM/s320/generator.jpg' border='1' /&gt;&lt;p&gt;Generators can transform AST directly into real files:&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S-fQFM6naYI/AAAAAAAAAbg/heBXUZLGWTo/s320/ast_to_file.jpg' border='1' /&gt;&lt;p&gt;&amp;#8230;or they can transform AST into another AST. This is useful when you want to build your language on top of another language. For example, in MPS there a bundled language called &lt;a href='http://confluence.jetbrains.net/display/MPS/Base+Language'&gt;base language&lt;/a&gt; which is basically Java extended with features like closures. You can create generator to translate your language into base language and generator from base language will automatically transform it into java files:&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S-fQGjVVdmI/AAAAAAAAAbo/FF9xGvg4Zzk/s640/ast_to_ast.jpg' border='1' /&gt;&lt;p&gt;This way you have a chain of AST transformations and don&amp;#8217;t have to deal with file generation.&lt;/p&gt;&lt;p&gt;You can read more about generators &lt;a href='http://confluence.jetbrains.net/display/MPS/Generator'&gt;here&lt;/a&gt;. There are also quite good &lt;a href='http://confluence.jetbrains.net/display/MPS/Generator+Demos'&gt;generator demos&lt;/a&gt;.&lt;/p&gt;&lt;h1 id='whats_next'&gt;What&amp;#8217;s next?&lt;/h1&gt;&lt;p&gt;There are a lot of other interesting things in MPS like type system, IDE support and much more, but to do something useful you don&amp;#8217;t have to know anything except editors and generators. In my view, the best way to get started is to go through &lt;a href='http://www.jetbrains.com/mps/docs/tutorial.html'&gt;MPS tutorial&lt;/a&gt; and &lt;a href='http://confluence.jetbrains.net/display/MPS/Generator+Demos'&gt;generator demos&lt;/a&gt;. Do not just read them and look at screenshots, install MPS and try to repeat all the steps. Be aware, that tutorials are not too easy and might cover too many topics to understand at once. Don&amp;#8217;t get frustrated if something is not clear. After tutorials you might read parts of &lt;a href='http://confluence.jetbrains.net/display/MPS/MPS+User&amp;apos;s+Guide'&gt;user guide&lt;/a&gt; or try doing something simple yourself. It doesn&amp;#8217;t take a lot of time, but it&amp;#8217;s rewarding and it&amp;#8217;s the best way to understand what MPS is good for.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-8799571119913275761?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=bYjfLuUZCLA:W9i3u60LC2E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=bYjfLuUZCLA:W9i3u60LC2E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=bYjfLuUZCLA:W9i3u60LC2E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=bYjfLuUZCLA:W9i3u60LC2E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=bYjfLuUZCLA:W9i3u60LC2E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=bYjfLuUZCLA:W9i3u60LC2E:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=bYjfLuUZCLA:W9i3u60LC2E:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=bYjfLuUZCLA:W9i3u60LC2E:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/bYjfLuUZCLA" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-10T03:08:01.862-07:00</app:edited><media:thumbnail url="http://2.bp.blogspot.com/_VrU0ZHx_ziY/S-e6f5CFqhI/AAAAAAAAAaw/i6Pc1SPxhok/s72-c/ast.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2010/05/mps-is-simple.html</feedburner:origLink></item><item><title>Pomodoro in practice</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/BDjcOXo0StI/pomodoro-in-practice.html</link><category>psychology</category><category>pomodoro</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Thu, 15 Apr 2010 10:51:21 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-7850765179027667987</guid><description>&lt;p&gt;Do you ever feel at work like you&amp;#8217;re doing thousand things at the same time but never finish anything? You start writing some code, then a bug report comes in and you have to respond because it stops QA from testing. You go back to code, but then colleague comes with a question. Then yo go to meeting. You go back to code again, but it doesn&amp;#8217;t go very well so you start reading blogs. Then you receive an email you have respond to. And before you know the day is over and you don&amp;#8217;t feel like you have really accomplished anything.&lt;/p&gt;&lt;p&gt;If you experience anything like this, stop doing what you&amp;#8217;re doing and try &lt;a href='http://www.pomodorotechnique.com'&gt;pomodoro&lt;/a&gt;.&lt;/p&gt;&lt;h1 id='what_is_pomodoro'&gt;What is pomodoro?&lt;/h1&gt;&lt;p&gt;It&amp;#8217;s a focus (and time) management technique or put more simply &amp;#8220;a way to have less distractions&amp;#8221;. In its basic form pomodoro is like this:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;you do a task for 25 minutes avoiding any interruptions;&lt;/li&gt;&lt;li&gt;after 25 minutes you take 5 minute break;&lt;/li&gt;&lt;li&gt;if despite all your efforts, you&amp;#8217;re distracted during 25 minutes, you reset timer and this pomodoro doesn&amp;#8217;t count.&lt;/li&gt;&lt;/ul&gt;&lt;div class='separator' style='clear: both; text-align: center;'&gt;&lt;a href='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S8dRRZIQXYI/AAAAAAAAAag/y-KkZdjEpkw/s1600/pomodoro.jpg' imageanchor='1' style='clear: right; float: right; margin-bottom: 1em; margin-left: 1em;'&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S8dRRZIQXYI/AAAAAAAAAag/y-KkZdjEpkw/s200/pomodoro.jpg' border='0' height='159' width='200' /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;(Notice, that &amp;#8220;pomodoro&amp;#8221; term is overloaded, because &amp;#8220;pomodoro&amp;#8221; is not only the name of the technique, it also means 25 minute interval.)&lt;/p&gt;&lt;p&gt;The main reason to do it is that any non-trivial task requires a lot of mental effort to get into &lt;a href='http://en.wikipedia.org/wiki/Flow_(psychology)'&gt;the state of flow&lt;/a&gt; (a state of mind when you&amp;#8217;re really productive). Getting into the &lt;a href='http://en.wikipedia.org/wiki/Flow_(psychology)'&gt;flow&lt;/a&gt; is quite expensive so you should avoid all the &lt;em&gt;internal&lt;/em&gt; (checking email, reading RSS) and &lt;em&gt;external&lt;/em&gt; (a colleague taking to you, instant messenger pop-up) interruptions.&lt;/p&gt;&lt;p&gt;On the other hand, working for 10 hours in a row is also not productive. It&amp;#8217;s also important to have small breaks. I remember quite a few examples when after hours of hectic coding I realized that I had created a mess, while there is a much simpler solution to my problem, or even worse that the problem was wrong.&lt;/p&gt;&lt;p&gt;There is more to it, but in a nutshell pomodoro is like a vise:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;forces you to concentrate on the task by having less interruptions;&lt;/li&gt;&lt;li&gt;forces you to have breaks.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;(Another metaphor I like &amp;#8220;pomodoro is your personal Scrum sprint&amp;#8221;.)&lt;/p&gt;&lt;h1 id='pomodoro_in_practice'&gt;Pomodoro in practice&lt;/h1&gt;&lt;p&gt;I&amp;#8217;ve been using pomodoro for about 4 months now. In three words &amp;#8220;it is great&amp;#8221;. In ten words &amp;#8220;It&amp;#8217;s not a silver bullet, but totally worth doing&amp;#8221;.&lt;/p&gt;&lt;h1 id='what_works'&gt;What works&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;I get more satisfaction. Having small tasks and accomplishing them is somehow more satisfying than doing the same amount of work without tasks (I think, it&amp;#8217;s also one of the ideas in &lt;a href='http://www.amazon.com/Getting-Things-Done-Stress-Free-Productivity/dp/0142000280'&gt;Getting things done&lt;/a&gt;). It works especially well on the most insane days because doing small focused tasks makes them less insane and at the very least at the end of the day you can look at the paper where you track pomodoros and see that you have actually accomplished something.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;makes the cost of context switching explicit. It&amp;#8217;s explicit for me because I know that I&amp;#8217;m doing a certain task and if I&amp;#8217;m distracted I&amp;#8217;ll have to reset timer. It&amp;#8217;s explicit for others because they know I&amp;#8217;m doing pomodoro and they can see my timer. (I use &lt;a href='http://www.focusboosterapp.com/'&gt;Focus Booster&lt;/a&gt; on Windows and &lt;a href='http://www.apple.com/downloads/macosx/development_tools/pomodoro.html'&gt;Pomodoro&lt;/a&gt; on Mac OS.)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;less procrastination. Before each pomodoro I choose a task (or several tasks if they&amp;#8217;re small) that I&amp;#8217;m going to accomplish. If something has to be done to accomplish the task, I do it immediately. With 25 minute &amp;#8220;sprints&amp;#8221; there no time to procrastinate. It works especially well with tasks which are not exciting but just have to be done.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;time tracking. I used to track how much time I spend on tasks before using pomodoro. With pomodoro time tracking became easier and better. Easier because I do it anyway whenever I use pomodoro. Better because my time is tracked with 100% focus factor.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;focus factor. &amp;#8220;Focus factor&amp;#8221; a term from Agile (see &lt;a href='http://www.infoq.com/minibooks/scrum-xp-from-the-trenches'&gt;XP and Scrum from trenches&lt;/a&gt;). What I mean here is how much time a day you can spend without being interrupted. With pomodoro you get your personal focus factor for free. On average I can do 8 pomodoros or 4 hours of uninterrupted work. This is 50% focus factor. (It may seem low, but it&amp;#8217;s better to know the truth than to avoid it.)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;having breaks is relaxing. It helps a lot to keep focus while doing boring tasks because I know I&amp;#8217;ll have a break after all :)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;it&amp;#8217;s fun. It&amp;#8217;s like a game, but really useful one.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1 id='what_doesnt_work'&gt;What doesn&amp;#8217;t work&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;often 25 minutes is not enough. I haven&amp;#8217;t figured out the reason yet. Probably, it depends on the time of the day and kind of task. When I do something really exciting, I tend to skip every second break.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;obeying the timer. When I started using pomodoro, I would actually start or stop doing task when timer rang. I don&amp;#8217;t know whether I adopted pomodoro to my needs or I&amp;#8217;m just lazy, but now I don&amp;#8217;t care about timer that much. I can stop few minutes later or have a longer break if I feel like doing it.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;exploratory tasks. Pomodoro is great for goal oriented tasks but being goal-oriented is not always a good thing (see awesome talk by &lt;a href='http://www.ted.com/talks/dan_pink_on_motivation.html'&gt;Daniel Pink&lt;/a&gt;). Sometimes you may want to enjoy yourself without thinking of time or how much you can accomplish. I don&amp;#8217;t watch movies or read books using pomodoro.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;breaks can be distracting if you involve in a discussion.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;some people don&amp;#8217;t care about pomodoro. Even though they know what it is, even though they see timer, they keep distracting me anyway. It&amp;#8217;s not a big deal, just the way it is.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;since pomodoro is like a game, you may start cheating yourself to get better results and more satisfaction. For example, I noticed that I reset pomodoro less often than I used to three months ago.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1 id='consequences'&gt;Consequences&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;I feel happier. Even if have to do something really boring. &lt;div class='separator' style='clear: both; text-align: center;'&gt;&lt;a href='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S8dRe-iaEaI/AAAAAAAAAao/QMzfPhti37I/s1600/Tomato_Icons.jpg' imageanchor='1' style='clear: right; float: right; margin-bottom: 1em; margin-left: 1em;'&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S8dRe-iaEaI/AAAAAAAAAao/QMzfPhti37I/s200/Tomato_Icons.jpg' border='0' height='148' width='200' /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;I have less distractions:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;I turned off email and instant messenger&amp;#8217;s notifications;&lt;/li&gt;&lt;li&gt;I check instant messenger only when decide to do it, not when someone sends me a message;&lt;/li&gt;&lt;li&gt;I broke email addiction. I don&amp;#8217;t check email or read RSS feeds when I feel like I&amp;#8217;m bored.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;I became more realistic in task estimates (at least I want to think so).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;I became more productive.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1 id='try_pomodoro_now'&gt;Try pomodoro now!&lt;/h1&gt;&lt;p&gt;I started using pomodoro by simply typing &amp;#8220;pomodoro timer&amp;#8221; in google and choosing a timer. I installed &lt;a href='http://www.focusboosterapp.com/'&gt;Focus Booster&lt;/a&gt; and started my first pomodoro without knowing too much about it. You&amp;#8217;re not going to lose anything, but there is a chance to get rid of distractions and become happier :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-7850765179027667987?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=BDjcOXo0StI:9G1kTXly9zE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=BDjcOXo0StI:9G1kTXly9zE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=BDjcOXo0StI:9G1kTXly9zE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=BDjcOXo0StI:9G1kTXly9zE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=BDjcOXo0StI:9G1kTXly9zE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=BDjcOXo0StI:9G1kTXly9zE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=BDjcOXo0StI:9G1kTXly9zE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=BDjcOXo0StI:9G1kTXly9zE:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/BDjcOXo0StI" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-15T10:51:21.340-07:00</app:edited><media:thumbnail url="http://3.bp.blogspot.com/_VrU0ZHx_ziY/S8dRRZIQXYI/AAAAAAAAAag/y-KkZdjEpkw/s72-c/pomodoro.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2010/04/pomodoro-in-practice.html</feedburner:origLink></item><item><title>Meta Programming System: generator for Miss Grant's controller</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/ExbTmGTB5e4/meta-programming-system-generator-for.html</link><category>mps</category><category>state machine</category><category>Martin Fowler</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Sun, 04 Apr 2010 01:32:11 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-86121069670622147</guid><description>&lt;p&gt;This is the second part of Martin Fowler&amp;#8217;s state machine example in MPS. The &lt;a href='http://codingmatters.blogspot.com/2010/02/martin-fowlers-state-machine-in-mps.html'&gt;first one&lt;/a&gt; was about creating editor for &lt;a href='http://www.martinfowler.com/dslwip/Intro.html#ProgrammingMissGrantsController'&gt;Miss Grant&amp;#8217;s Controller&lt;/a&gt; and at the end of it there was a nice editor like this:&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fDgfN0j6I/AAAAAAAAANo/wsHDnN6k0n4/s640/Pasted+Graphic+2.jpg' border='0' /&gt;&lt;p&gt;While this is cool, this editor doesn&amp;#8217;t help to create anything useful like Java code which you could actually execute. So this part will be about code generation for &lt;a href='http://www.martinfowler.com/dslwip/Intro.html#ProgrammingMissGrantsController'&gt;Miss Grant&amp;#8217;s Controller&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;h1 id='what_its_going_to_be_like_in_the_end'&gt;What it&amp;#8217;s going to be like in the end?&lt;/h1&gt;&lt;p&gt;There will be java code based on existing set of java classes. Something like this:&lt;/p&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S7Tzd5BafNI/AAAAAAAAAUM/RdLXDXapY7M/s640/1.jpg' border='0' /&gt;&lt;h1 id='importing_java_classes'&gt;Importing java classes&lt;/h1&gt;&lt;p&gt;In &lt;a href='http://www.martinfowler.com/dslwip/Intro.html'&gt;introductory example&lt;/a&gt; Martin Fowler shows some code and a diagram to explain what the state machine is like. To reproduce this state machine framework I copied all the code from &lt;a href='http://www.martinfowler.com/dslwip/Intro.html'&gt;introductory example&lt;/a&gt; into IDE. (There are some problems with code, so if you try doing it yourself, don&amp;#8217;t expect it to compile out-of-the-box.) I also didn&amp;#8217;t feel ok copying diagram or linking to it (after all it&amp;#8217;s a part of the book), so here is a diagram I got in IntelliJ after copy-pasting code and making some minor changes:&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S7T2iGyEyxI/AAAAAAAAAUU/zjS9AEVRvI8/s640/Pasted+Graphic.jpg' border='0' /&gt;&lt;p&gt;In a way this diagram is very similar to AST from &lt;a href='http://codingmatters.blogspot.com/2010/02/martin-fowlers-state-machine-in-mps.html'&gt;the previous part&lt;/a&gt;. &lt;strong&gt;StateMachine&lt;/strong&gt; receives &lt;strong&gt;Events&lt;/strong&gt; and changes its &lt;strong&gt;State&lt;/strong&gt;. &lt;strong&gt;States&lt;/strong&gt; can have several rules called &lt;strong&gt;Transitions&lt;/strong&gt; describing which &lt;strong&gt;State&lt;/strong&gt; &lt;strong&gt;StateMachine&lt;/strong&gt; will be in after receiving some &lt;strong&gt;Event&lt;/strong&gt;. When state machine transitions to a new state, it executes &lt;strong&gt;Commands&lt;/strong&gt; associated with new &lt;strong&gt;State&lt;/strong&gt;. There is also &lt;strong&gt;StateMachineFactory&lt;/strong&gt; which creates &lt;strong&gt;StateMachines&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;First off, let&amp;#8217;s create generator and empty template.&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S7T4mBqez-I/AAAAAAAAAUc/JIj0co5ATzo/s640/MPS-8.jpg' border='0' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S7T40yIdKvI/AAAAAAAAAUk/yfiJcYzqcDc/s640/MPS-9.jpg' border='0' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S7T7mrUEr9I/AAAAAAAAAUs/bRvPE9emNSI/s640/System-1.jpg' border='0' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S7T8IhdJuPI/AAAAAAAAAU0/svd2A_LuYrA/s640/MF_stateMachine.mpr+-+MF_stateMachine.generator.template.main%40generator_null+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;p&gt;In order to use existing java classes in template, we need to add these java classes to MPS project:&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S7T9ageOF3I/AAAAAAAAAU8/BG-hYF9KbOw/s640/MPS-10.jpg' border='0' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S7T9i3j6WxI/AAAAAAAAAVE/7CH8tX35LNY/s640/MF_stateMachine+Properties-1.jpg' border='0' /&gt;&lt;p&gt;After adding classes to language properties we have to import them into template. There are two ways to do it. The simple one is to press Ctrl+M and start typing package name:&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S7T-MbcFcgI/AAAAAAAAAVM/0dfcXd7ZAZA/s640/MF_stateMachine.mpr+-+MF_stateMachine.structure_CommandRef+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;p&gt;The more complicated way is to add package in generator properties:&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S7T-ikteo1I/AAAAAAAAAVU/1i8ZUSGmakQ/s640/MPS-11-1.jpg' border='0' /&gt;&lt;p&gt;After importing the package we&amp;#8217;ll be able to use all the state machine classes in template code:&lt;/p&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S7T_2VGWNdI/AAAAAAAAAVk/S4KkmAdqFFU/s640/MPS-12.jpg' border='0' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S7T_nOx6M_I/AAAAAAAAAVc/LFXjcSJg53U/s640/MF_stateMachine.mpr+-+MF_stateMachine.generator.template.main%40generator_MyStateMachineFactory+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;p&gt;Now that we have simple template let&amp;#8217;s map StateMachine concept to this template&amp;#8230;&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S7UAZj71noI/AAAAAAAAAVs/iVOO26ksAuA/s640/MF_stateMachine.mpr+-+MF_stateMachine.generator.template.main%40generator_main+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fGtsl2UNI/AAAAAAAAAO4/rswOdzo6Oso/s640/generation.jpg' border='0' /&gt;&lt;p&gt;&amp;#8230; and see if it&amp;#8217;s working&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S7UAmMFFPaI/AAAAAAAAAV0/HS54FSyFtRQ/s640/System-2.jpg' border='0' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S7UAwSUzAgI/AAAAAAAAAV8/CcLOOlAlJE0/s640/MF_stateMachine.mpr+-+MF_stateMachine.generator.template.main%40generator_main+-+JetBrains+MPS+1.1+-2.jpg' border='0' /&gt;&lt;h1 id='adding_initialstate'&gt;Adding initialState&lt;/h1&gt;&lt;p&gt;Before going further it worth noticing that there is probably a missing part in Martin Fowler&amp;#8217;s example. There is a notion of resetEvents which return state machine to its initial state and there is even code which does it&amp;#8230;&lt;/p&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S7YrHUPa-_I/AAAAAAAAAWM/1rYRotiMgEE/s640/MF_StateMachine+-+%5B_Users_dima_IdeaProjects_MF_StateMachine%5D+-+%5BMF_StateMachine%5D+-+..._src_mf_statemachine_StateMachine.java+-+IntelliJ+IDEA+9.0.1-1.jpg' border='0' /&gt;&lt;p&gt;&amp;#8230; but state machine DSL doesn&amp;#8217;t have any constructs to specify initial state. Let&amp;#8217;s fix it by adding reference to StateMachine concept:&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S7Yrffdl9CI/AAAAAAAAAWU/D0_OOEgkjnc/s640/MF_stateMachine.mpr+-+MF_stateMachine.structure_StateMachine+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S7YroUgQqqI/AAAAAAAAAWc/sVkgUx6KedE/s640/MF_stateMachine.mpr+-+MF_stateMachine.structure_StateMachine+-+JetBrains+MPS+1.1+-2.jpg' border='0' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fGtsl2UNI/AAAAAAAAAO4/rswOdzo6Oso/s640/generation.jpg' border='0' /&gt;&lt;p&gt;Let&amp;#8217;s also configure initial state to idle, as it is in the &lt;a href='http://www.martinfowler.com/dslwip/Intro.html'&gt;introductory example&lt;/a&gt;.&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S7YsF3kTN3I/AAAAAAAAAWk/LPuWNs7bvBY/s320/MF_stateMachine.mpr+-+MF_stateMachine.sandbox.sandbox_Miss+Grant+-+JetBrains+MPS+1.1+-1.jpg' border='0' /&gt;&lt;h1 id='generating_events_commands_and_states'&gt;Generating Events, Commands and States&lt;/h1&gt;&lt;p&gt;First off, let&amp;#8217;s make generated class name more descriptive by prefixing it with state machine name. In editor state machine name is the topmost line:&lt;/p&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S7YsZeCcbkI/AAAAAAAAAWs/dPwjJ-WF9jo/s640/secretLangauage.mpr+-+secretLangauage.sandbox.sandbox_Miss+Grant+-+JetBrains+MPS+1.1+-2.jpg' border='0' /&gt;&lt;p&gt;We add it as property macro and replace spaces in state machine name, otherwise it will be invalid java class name.&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S7Ys3pya7_I/AAAAAAAAAW0/i45DwqJv-2k/s640/Inspector-2.jpg' border='0' /&gt;&lt;p&gt;Let&amp;#8217;s add generating code to create Event, Command and State objects. It will cover the following areas of the state machine DSL (note that State objects won&amp;#8217;t be fully configured after this step):&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S7YuxAqORfI/AAAAAAAAAW8/tDdVxIOY_d8/s640/1__%23%24%21%40%25%21%23__Pasted+Graphic.jpg' border='0' /&gt;&lt;p&gt;Let&amp;#8217;s start writing template by adding some code as if it was written in plain java. Code for creating Event object will be like this:&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S7YvEvHuZCI/AAAAAAAAAXE/F_4JikfMuoI/s640/MF_stateMachine.mpr+-+MF_stateMachine.generator.template.main%40generator_MyStateMachineFactory+-+JetBrains+MPS+1.1+-1.jpg' border='0' /&gt;&lt;p&gt;Now we can add macros to &lt;strong&gt;loop&lt;/strong&gt; over all the events:&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S7YvbN8yaGI/AAAAAAAAAXM/WOsCfqMhqSA/s640/System-3-1.jpg' border='0' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S7Yzk6VykSI/AAAAAAAAAXc/rCPabkYzwG8/s640/2__%23%24%21%40%25%21%23__Pasted+Graphic.jpg' border='0' /&gt;&lt;p&gt;Inside the $LOOP$ macro we add property macro to change variable name for each loop cycle:&lt;/p&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S7Y0CgJ3pjI/AAAAAAAAAXk/96LR492Zloc/s640/System-4.jpg' border='0' /&gt;&lt;p&gt;Similarly we wrap with property macros event &amp;#8220;name&amp;#8221; and &amp;#8220;code&amp;#8221; parameters. After writing similar macros for Command and State, template will look like this:&lt;/p&gt;&lt;img src='http://lh3.ggpht.com/_VrU0ZHx_ziY/S7Y1WIYAzTI/AAAAAAAAAX8/kyw4PHBlyAE/s640/MF_stateMachine.mpr%20-%20MF_stateMachine.generator.template.main%40generator_MyStateMachineFactory%20-%20JetBrains%20MPS%201.1%20-2.jpg' border='0' /&gt;&lt;p&gt;Let&amp;#8217;s see what this template generates&amp;#8230;&lt;/p&gt;&lt;img src='http://lh4.ggpht.com/_VrU0ZHx_ziY/S7Y13oirLBI/AAAAAAAAAYE/MjYWz5m2pHw/s640/MPS-13.jpg' border='0' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S7Y2u0SutgI/AAAAAAAAAY0/yx88BCEXpds/s640/MPS-14-1.jpg' border='0' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S7Y27-pmkOI/AAAAAAAAAY8/T3pf21Ah7Es/s640/MF_stateMachine.mpr+-+MF_stateMachine.sandbox.sandbox_Miss+Grant+-+JetBrains+MPS+1.1+-3.jpg' border='0' /&gt;&lt;h1 id='generating_initial_state'&gt;Generating initial state&lt;/h1&gt;&lt;p&gt;So far we&amp;#8217;ve been generating code which instantiates StateMachine with &lt;em&gt;null&lt;/em&gt; initial state. Let&amp;#8217;s add macro to initialize it with real state. We replace &lt;em&gt;null&lt;/em&gt; with reference to state variable and wrap this variable with &lt;strong&gt;reference macro&lt;/strong&gt;:&lt;/p&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S7Y41mGJidI/AAAAAAAAAZE/B_7I2SzXuF8/s640/System-5.jpg' border='0' /&gt;&lt;p&gt;Reference macro can return &lt;em&gt;node&lt;/em&gt; or &lt;em&gt;string&lt;/em&gt; so we just copy initial state name (which is string) from StateMachine node:&lt;/p&gt;&lt;img src='http://lh5.ggpht.com/_VrU0ZHx_ziY/S7Y-oUmVuOI/AAAAAAAAAZM/TislmRq1ugE/s640/Inspector-4.jpg' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://lh5.ggpht.com/_VrU0ZHx_ziY/S7Y-_2FXR8I/AAAAAAAAAZU/9ht5b89jdlw/s640/Go%20To-1.jpg' /&gt;&lt;p&gt;After generation StateMachine will be constructed with idle initial state.&lt;/p&gt;&lt;img src='http://lh6.ggpht.com/_VrU0ZHx_ziY/S7Y_f5o0ecI/AAAAAAAAAZc/xfqeZzLFJ5o/s640/MF_stateMachine.mpr%20-%20MF_stateMachine.sandbox.sandbox_Miss%20Grant%20-%20JetBrains%20MPS%201.1%20-4.jpg' /&gt;&lt;h1 id='adding_transitions_and_actions'&gt;Adding transitions and actions&lt;/h1&gt;&lt;p&gt;Event and Command objects are now fully constructed but States has yet to be configured with transitions and actions. Let&amp;#8217;s start by writing template code for adding transition as if it was plain java:&lt;/p&gt;&lt;img src='http://lh6.ggpht.com/_VrU0ZHx_ziY/S7ZAS6zcdLI/AAAAAAAAAZg/hrKqMuRRwFg/s640/MF_stateMachine.mpr%20-%20MF_stateMachine.generator.template.main%40generator_MyStateMachineFactory%20-%20JetBrains%20MPS%201.1%20-4.jpg' /&gt;&lt;p&gt;What we want now is to copy that line for each transition in each state. In pseudo code it will look like this:&lt;/p&gt;&lt;img src='http://lh6.ggpht.com/_VrU0ZHx_ziY/S7ZCP-iU9ZI/AAAAAAAAAZo/Xo-9w0St6ZA/s640/MF_StateMachine%20-%20%5B_Users_dima_IdeaProjects_MF_StateMachine%5D%20-%20_scratch_2.txt%20-%20IntelliJ%20IDEA%209.0.1.jpg' /&gt;&lt;p&gt;At the end equivalent template code will be:&lt;/p&gt;&lt;img src='http://lh6.ggpht.com/_VrU0ZHx_ziY/S7ZCQJSDQyI/AAAAAAAAAZs/jOb8QzFEtCE/s640/Pasted%20Graphic%201.jpg' /&gt;&lt;p&gt;We start by creating outer loop&amp;#8230;&lt;/p&gt;&lt;img src='http://lh5.ggpht.com/_VrU0ZHx_ziY/S7ZCQeqllPI/AAAAAAAAAZw/O9eYIUioAxs/s640/System-7-1.jpg' /&gt;&lt;p&gt;&amp;#8230; and then inner loop&lt;/p&gt;&lt;img src='http://lh4.ggpht.com/_VrU0ZHx_ziY/S7ZCQSeAbbI/AAAAAAAAAZ0/uf7aUV71Tc4/s640/System-6-1.jpg' /&gt;&lt;p&gt;Parameterizing event and target state is easy. We can simply take names of triggerEvent and targetState references:&lt;/p&gt;&lt;img src='http://lh5.ggpht.com/_VrU0ZHx_ziY/S7ZD2BwWreI/AAAAAAAAAZ4/_MYhiXSqi5k/s640/Inspector-6-1.jpg' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://lh6.ggpht.com/_VrU0ZHx_ziY/S7ZD2S_C1OI/AAAAAAAAAZ8/TtKOHucjAQ0/s640/Inspector-7-1-1.jpg' /&gt;&lt;p&gt;Getting name of the current state is more complicated. The problem is that inner $LOOP$ macro doesn&amp;#8217;t know anything about outer $LOOP$ macro. There is a way to do it using mapping label (see &lt;a href='http://www.jetbrains.net/devnet/thread/287022?tstart=0'&gt;this thread&lt;/a&gt;) but in this case we can do it by taking Transition node&amp;#8217;s parent which is a State node:&lt;/p&gt;&lt;img src='http://lh4.ggpht.com/_VrU0ZHx_ziY/S7ZD2XoYHjI/AAAAAAAAAaA/tqO1D4Hhqlo/s640/Inspector-8.jpg' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://lh5.ggpht.com/_VrU0ZHx_ziY/S7Y-_2FXR8I/AAAAAAAAAZU/9ht5b89jdlw/s640/Go%20To-1.jpg' /&gt;&lt;p&gt;When generated, the code will look like this:&lt;/p&gt;&lt;img src='http://lh5.ggpht.com/_VrU0ZHx_ziY/S7hIgk8WzBI/AAAAAAAAAaE/EjmvJXnzUS4/s640/MF_stateMachine.mpr%20-%20MF_stateMachine.sandbox.sandbox_Miss%20Grant%20-%20JetBrains%20MPS%201.1%20-6.jpg' /&gt;&lt;p&gt;We do similar thing to generate addAction() statements.&lt;/p&gt;&lt;img src='http://lh3.ggpht.com/_VrU0ZHx_ziY/S7hIhDNWmtI/AAAAAAAAAaI/tQZk45XBGxA/s640/MF_stateMachine.mpr%20-%20MF_stateMachine.generator.template.main%40generator_MyStateMachineFactory%20-%20JetBrains%20MPS%201.1%20-6.jpg' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://lh5.ggpht.com/_VrU0ZHx_ziY/S7Y-_2FXR8I/AAAAAAAAAZU/9ht5b89jdlw/s640/Go%20To-1.jpg' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://lh5.ggpht.com/_VrU0ZHx_ziY/S7hIhZS7OSI/AAAAAAAAAaM/eod40oQw9sw/s640/MF_stateMachine.mpr%20-%20MF_stateMachine.sandbox.sandbox_Miss%20Grant%20-%20JetBrains%20MPS%201.1%20-7.jpg' /&gt;&lt;h1 id='reset_events'&gt;Reset events&lt;/h1&gt;&lt;p&gt;The only missing part now is reset events. This is pretty straightforward. We loop over resetEvents and use reference macro to generate parameter names forv addResetEvents() method.&lt;/p&gt;&lt;img src='http://lh4.ggpht.com/_VrU0ZHx_ziY/S7hJwDxTS-I/AAAAAAAAAaQ/I0DK1JkGqF4/s640/Inspector-10.jpg' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://lh5.ggpht.com/_VrU0ZHx_ziY/S7Y-_2FXR8I/AAAAAAAAAZU/9ht5b89jdlw/s640/Go%20To-1.jpg' /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src='http://lh5.ggpht.com/_VrU0ZHx_ziY/S7hJwfwjnyI/AAAAAAAAAaU/cA9dsXRsX1E/s640/MF_stateMachine.mpr%20-%20MF_stateMachine.sandbox.sandbox_Miss%20Grant%20-%20JetBrains%20MPS%201.1%20-8.jpg' /&gt;&lt;h1 id='setting_up_output_path'&gt;Setting up output path&lt;/h1&gt;&lt;p&gt;It&amp;#8217;s great to have generated code, but we need to be able to actually use it. Let&amp;#8217;s save generated files in the folder with source code from &lt;a href='http://www.martinfowler.com/dslwip/Intro.html'&gt;introductory example&lt;/a&gt;. It can be done in Solution properties by specifying generator output path:&lt;/p&gt;&lt;img src='http://lh4.ggpht.com/_VrU0ZHx_ziY/S7hKksIZlkI/AAAAAAAAAaY/b_qIYudfe8E/s640/Pasted%20Graphic%202.jpg' /&gt;&lt;p&gt;Now java project for &lt;a href='http://www.martinfowler.com/dslwip/Intro.html'&gt;introductory example&lt;/a&gt; can be configured to use src_gen folder as a source folder, so whenever state machine changes in MPS, generated files will be seen by IntelliJ.&lt;/p&gt;&lt;img src='http://lh4.ggpht.com/_VrU0ZHx_ziY/S7hKkuNlZZI/AAAAAAAAAac/loDYCTswTac/s640/MF_StateMachine%20-%20%5B_Users_dima_IdeaProjects_MF_StateMachine%5D%20-%20%5BMF_StateMachine%5D%20-%20..._src_gen_MF_stateMachine_sandbox_sandbox_Miss_Grant_StateMachine.java%20-%20IntelliJ%20IDEA%209.0.1.jpg' /&gt;&lt;h1 id='whats_next'&gt;What&amp;#8217;s next?&lt;/h1&gt;&lt;p&gt;While having all this code is great we still need:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;unit tests for state machine&lt;/li&gt;
&lt;li&gt;unit tests for state machine DSL&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-86121069670622147?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=ExbTmGTB5e4:ETAT7bYKYDY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=ExbTmGTB5e4:ETAT7bYKYDY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=ExbTmGTB5e4:ETAT7bYKYDY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=ExbTmGTB5e4:ETAT7bYKYDY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=ExbTmGTB5e4:ETAT7bYKYDY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=ExbTmGTB5e4:ETAT7bYKYDY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=ExbTmGTB5e4:ETAT7bYKYDY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=ExbTmGTB5e4:ETAT7bYKYDY:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/ExbTmGTB5e4" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-04T01:32:11.203-07:00</app:edited><media:thumbnail url="http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fDgfN0j6I/AAAAAAAAANo/wsHDnN6k0n4/s72-c/Pasted+Graphic+2.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2010/04/meta-programming-system-generator-for.html</feedburner:origLink></item><item><title>baseLang.collections.list and set cheatsheets</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/M38ez5X0Lwg/baselangcollectionslist-and-set.html</link><category>mps</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Mon, 08 Mar 2010 02:31:34 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-3166719770809016995</guid><description>Here are cheatsheets for &lt;b&gt;list&lt;/b&gt; and &lt;b&gt;set&lt;/b&gt; types from jetbrains.mps.baseLanguage.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;[...]&lt;/b&gt; is literal for sequence.&lt;br /&gt;
&lt;b&gt;should be&lt;/b&gt; is assertEquals() which can compare sequences.&lt;br /&gt;
&lt;b&gt;given list&lt;/b&gt; is equivalent to &lt;br /&gt;
&lt;pre&gt;{
  list&amp;lt;int&amp;gt; aList = new linkedlist&amp;lt;int&amp;gt;;
  aList.addAll(...);
  aList.someListOperation();
  ...
}
&lt;/pre&gt;&lt;br /&gt;
(Project source code is &lt;a href="http://github.com/dkandalov/MPS-baseLanguage-examples"&gt;here&lt;/a&gt;.)&lt;br /&gt;
&lt;br /&gt;
&lt;img alt="list_cheatsheet" height="1150" src="http://farm5.static.flickr.com/4054/4416041011_59109ac5b5_o.jpg" width="480" /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img alt="set_cheatsheet" height="585" src="http://farm5.static.flickr.com/4033/4416041013_aac3bceb3d_o.jpg" width="424" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-3166719770809016995?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=M38ez5X0Lwg:D15oBP8K158:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=M38ez5X0Lwg:D15oBP8K158:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=M38ez5X0Lwg:D15oBP8K158:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=M38ez5X0Lwg:D15oBP8K158:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=M38ez5X0Lwg:D15oBP8K158:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=M38ez5X0Lwg:D15oBP8K158:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=M38ez5X0Lwg:D15oBP8K158:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=M38ez5X0Lwg:D15oBP8K158:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/M38ez5X0Lwg" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-08T02:31:34.659-08:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2010/03/baselangcollectionslist-and-set.html</feedburner:origLink></item><item><title>baseLang.collections.sequence cheatsheet</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/iAMtpkYUR00/baselangcollectionsequence-cheatsheet.html</link><category>mps</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Mon, 08 Mar 2010 02:33:20 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-7619169774930824615</guid><description>Here is a cheatsheet for sequence type from jetbrains.mps.baseLanguage. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;[...]&lt;/b&gt; is literal for sequence I came up with.&lt;br /&gt;
&lt;b&gt;should be&lt;/b&gt; is assertEquals() which can compare sequences.&lt;br /&gt;
&lt;br /&gt;
(Project source code is &lt;a href="http://github.com/dkandalov/MPS-baseLanguage-examples"&gt;here&lt;/a&gt;.)&lt;br /&gt;
&lt;br /&gt;
&lt;img src="http://farm5.static.flickr.com/4067/4416783026_4aa0abae9a_o.jpg" width="1124" height="950" alt="sequence_cheatsheet" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-7619169774930824615?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=iAMtpkYUR00:1L7HLYagevA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=iAMtpkYUR00:1L7HLYagevA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=iAMtpkYUR00:1L7HLYagevA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=iAMtpkYUR00:1L7HLYagevA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=iAMtpkYUR00:1L7HLYagevA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=iAMtpkYUR00:1L7HLYagevA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=iAMtpkYUR00:1L7HLYagevA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=iAMtpkYUR00:1L7HLYagevA:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/iAMtpkYUR00" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-08T02:33:20.890-08:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2010/03/baselangcollectionsequence-cheatsheet.html</feedburner:origLink></item><item><title>Meta Programming System: editor for Miss Grant's controller</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/3aHL8ZKQZmo/martin-fowlers-state-machine-in-mps.html</link><category>mps</category><category>state machine</category><category>Martin Fowler</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Mon, 15 Feb 2010 13:42:52 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-1776518832406579575</guid><description>&lt;p&gt;I&amp;#8217;ve been playing with &lt;a href='http://www.jetbrains.com/mps/index.html'&gt;MPS&lt;/a&gt; over the last couple months so I felt like I have to write something about it. Here is Martin Fowler&amp;#8217;s &lt;a href='http://www.martinfowler.com/dslwip/Intro.html'&gt;introductory example&lt;/a&gt; from his upcoming &lt;a href='http://www.martinfowler.com/dslwip/'&gt;book about DSLs&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If you haven&amp;#8217;t read &lt;a href='http://www.martinfowler.com/dslwip/Intro.html'&gt;introductory example&lt;/a&gt;, it might be a good idea to take a look now because without it the following example won&amp;#8217;t make much sense. I will also assume that you know basics of MPS and at least have read &lt;a href='http://www.jetbrains.com/mps/docs/tutorial.html'&gt;MPS tutorial&lt;/a&gt;.&lt;/p&gt;&lt;h1 id='what_its_going_to_be_like_in_the_end'&gt;What it&amp;#8217;s going to be like in the end?&lt;/h1&gt;&lt;p&gt;There will be nice editor for state machine language with text completion and syntax highlighting. The syntax will be close to &lt;a href='http://www.martinfowler.com/dslwip/Intro.html#ProgrammingMissGrantsController'&gt;Miss Grant&amp;#8217;s Controller&lt;/a&gt;. Something like this:&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fDgfN0j6I/AAAAAAAAANo/wsHDnN6k0n4/s640/Pasted+Graphic+2.jpg' border='0' /&gt;&lt;p&gt;(To be fair, there is already secretCompartmentLanguage bundled with MPS which is kind of the same thing. There are some differences between Martin Fowler&amp;#8217;s example and secretCompartmentLanguage, though. In secretCompartmentLanguage there are no commands and states don&amp;#8217;t have actions.)&lt;/p&gt;&lt;br /&gt;&lt;h1 id='editors_for_statemachine_event_and_command'&gt;Editors for StateMachine, Event and Command&lt;/h1&gt;&lt;p&gt;First off, let&amp;#8217;s create concepts for &lt;a href='http://en.wikipedia.org/wiki/Abstract_syntax_tree'&gt;AST&lt;/a&gt; which will be used in editors. We have &lt;strong&gt;state machine&lt;/strong&gt; which receives &lt;strong&gt;events&lt;/strong&gt;, changes its &lt;strong&gt;state&lt;/strong&gt; and sends &lt;strong&gt;commands&lt;/strong&gt;. Here is the first version of StateMachine, Event, Command and State:&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fG4NGtABI/AAAAAAAAAPg/ct8qPjFt1aI/s400/MF_stateMachine+-+MF_stateMachine.structure_StateMachine+-+JetBrains+MPS+1.1+-3.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3fGyBZGxYI/AAAAAAAAAPI/L0tZ2WTP7L0/s320/MF_stateMachine+-+MF_stateMachine.structure_Event+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fGwvXXDiI/AAAAAAAAAPA/XG6hrnATWeI/s320/MF_stateMachine+-+MF_stateMachine.structure_Command+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fG28a6X-I/AAAAAAAAAPY/Jr4ZyPfTVTw/s320/MF_stateMachine+-+MF_stateMachine.structure_State+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;br /&gt;&lt;p&gt;Note that all concepts implement INamedConcept interface and both Event and Command implement IHaveCode:&lt;/p&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3fG078rvwI/AAAAAAAAAPQ/8Cd-_a7pxQM/s320/MF_stateMachine+-+MF_stateMachine.structure_IHaveCode+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;br /&gt;&lt;p&gt;Now when we have concept let&amp;#8217;s create editor for StateMachine:&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S3fGXV86unI/AAAAAAAAANw/AfJx6KegSiQ/s400/Pasted+Graphic+4.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3fGZLBGjCI/AAAAAAAAAN4/YNJ_f07RVhI/s400/Pasted+Graphic+5.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S3fGaflSYwI/AAAAAAAAAOA/I1TAP5mEjXk/s400/Pasted+Graphic+8.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3fGc69bnDI/AAAAAAAAAOI/ZZepv1hrXC8/s640/Pasted+Graphic+9.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fGd7FdMqI/AAAAAAAAAOQ/t3CP9t7RxmU/s400/Pasted+Graphic+10.jpg' border='0' /&gt;&lt;br /&gt;&lt;p&gt;After all the changes editor for StateMachine will look like this (note that cell collections for %event%, %command% and %state% are vertical):&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S3fOoGGjLBI/AAAAAAAAAQA/TY1AQIkLDTI/s400/Pasted+Graphic+18.jpg' border='0' /&gt;&lt;p&gt;Let&amp;#8217;s create simple editors for Event and Command concepts&amp;#8230;&lt;/p&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fOljNmOmI/AAAAAAAAAPw/2EHRdKNpCZg/s320/Pasted+Graphic+12.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fOnOO43rI/AAAAAAAAAP4/W_Cg2YKyWCo/s320/Pasted+Graphic+13.jpg' border='0' /&gt;&lt;p&gt;&amp;#8230; and this is it. On the whole editors will work like this:&lt;/p&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3fOkOv2j9I/AAAAAAAAAPo/2ieZ722LpQA/s640/OpenOffice.org.jpg' border='0' /&gt;&lt;p&gt;After generating language &amp;#8230;&lt;/p&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fGtsl2UNI/AAAAAAAAAO4/rswOdzo6Oso/s400/generation.jpg' border='0' /&gt;&lt;p&gt;&amp;#8230; we&amp;#8217;ll be able to create instance of StateMachine concept and actually use state machine editor:&lt;/p&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fGe9jV8qI/AAAAAAAAAOY/eDHskfwNub8/s640/Pasted+Graphic+14.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3fGktW4qvI/AAAAAAAAAOg/1q3dHjO214E/s320/Pasted+Graphic+16.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3fGmFOOxbI/AAAAAAAAAOo/mZtbn9M-FA0/s320/Pasted+Graphic+20.jpg' border='0' /&gt;&lt;h1 id='reset_events_for_state_machine'&gt;Reset events for state machine&lt;/h1&gt;&lt;p&gt;In his state machine Martin Fowler has notion of &lt;strong&gt;reset events&lt;/strong&gt;. Events which return machine to its initial state. In terms of our language AST, reset events are just links (or references) to already defined events. Let&amp;#8217;s add resetEvent reference to StateMachine concept:&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S3fZ2TcifuI/AAAAAAAAAQQ/RgpU-TckfZk/s400/mps_MF_example.rtfd-1-2.jpg' border='0' /&gt;&lt;p&gt;Turns out that unlike child nodes, there can&amp;#8217;t be references to multiple nodes (this is not conceptual problem, &amp;#8221;&lt;a href='http://www.jetbrains.net/devnet/thread/286194?tstart=0'&gt;it&amp;#8217;s just not implemented&lt;/a&gt;&amp;#8221;). As a workaround let&amp;#8217;s create EventRef concept which will hold one reference to Event. Then, we&amp;#8217;ll be able to add several EventRefs as StateMachine children.&lt;/p&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3fZ4giAyQI/AAAAAAAAAQo/I5rjPTObTuI/s400/MF_stateMachine+-+MF_stateMachine.structure_EventRef+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fZ3AlI5cI/AAAAAAAAAQY/RhsnE6SNxpM/s400/MF_stateMachine+-+MF_stateMachine.structure_StateMachine+-+JetBrains+MPS+1.1+-2-2.jpg' border='0' /&gt;&lt;p&gt;Because EventRef concept is different from Event, we&amp;#8217;ll need new editor for EventRef which will show name of Event it references to:&lt;/p&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fZ5dxfC8I/AAAAAAAAAQw/PG2P9lG6hfY/s320/MF_stateMachine+-+MF_stateMachine.structure_EventRef+-+JetBrains+MPS+1.1+-1-1.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fZ3mWi3ZI/AAAAAAAAAQg/57GohRxCmFo/s400/MF_stateMachine+-+MF_stateMachine.structure_StateMachine+-+JetBrains+MPS+1.1+-1-3.jpg' border='0' /&gt;&lt;p&gt;After language generation &amp;#8230;&lt;/p&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fGtsl2UNI/AAAAAAAAAO4/rswOdzo6Oso/s400/generation.jpg' border='0' /&gt;&lt;p&gt;&amp;#8230; editor for state machine will look like this:&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S3fZ18xU1rI/AAAAAAAAAQI/y6gTLcLMcDU/s320/MPS-2.jpg' border='0' /&gt;&lt;h1 id='editor_for_state_concept'&gt;Editor for State concept&lt;/h1&gt;&lt;p&gt;At the moment State concept is pretty much empty and doesn&amp;#8217;t have editor:&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fhOcDYnYI/AAAAAAAAAR4/CN_liDSNlVE/s320/1__%23%24%21%40%25%21%23__MF_stateMachine+-+MF_stateMachine.structure_State+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;p&gt;In Martin Fowler&amp;#8217;s example State have &lt;strong&gt;actions&lt;/strong&gt; (commands which are send on state entry) and &lt;strong&gt;transitions&lt;/strong&gt; (rules which say when state machine will change its state). Let&amp;#8217;s add actions to the State concept. There are multiple actions and they reference to already defined commands so there is the same problem as with resetEvents. We have to create CommandRef concept:&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S3fhNJ-P6lI/AAAAAAAAARo/9RAGly_vqII/s320/MF_stateMachine+-+MF_stateMachine.structure_CommandRef+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3fhNiaQMUI/AAAAAAAAARw/QKLIB3y_LY0/s320/MF_stateMachine+-+MF_stateMachine.structure_CommandRef+-+JetBrains+MPS+1.1+-1.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fhLFB0b1I/AAAAAAAAARQ/uX7WxHkhZPU/s320/MF_stateMachine+-+MF_stateMachine.structure_State+-+JetBrains+MPS+1.1+-3.jpg' border='0' /&gt;&lt;p&gt;Creating concept and editor for &lt;strong&gt;transition&lt;/strong&gt; is pretty much straightforward:&lt;/p&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3fhJcgRPbI/AAAAAAAAARA/U5TFAfJx_hE/s320/MF_stateMachine+-+MF_stateMachine.structure_Transition+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fhKVKT8xI/AAAAAAAAARI/VTVpt46Y5fo/s640/MF_stateMachine+-+MF_stateMachine.structure_State+-+JetBrains+MPS+1.1+-4.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fhMdSgXxI/AAAAAAAAARg/4odUJ7NGJfc/s320/MF_stateMachine+-+MF_stateMachine.structure_State+-+JetBrains+MPS+1.1+-1-1-1.jpg' border='0' /&gt;&lt;p&gt;Now we can create editor for the State and see how it works:&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fhL9K6SOI/AAAAAAAAARY/VRYjDok7Gtk/s640/MF_stateMachine+-+MF_stateMachine.structure_State+-+JetBrains+MPS+1.1+-2-1.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fGtsl2UNI/AAAAAAAAAO4/rswOdzo6Oso/s400/generation.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S3fhHF4fm8I/AAAAAAAAAQ4/7BfdFAioUtI/s320/MPS-3.jpg' border='0' /&gt;&lt;h1 id='add_action_intention'&gt;&amp;#8220;Add Action&amp;#8221; intention&lt;/h1&gt;&lt;p&gt;When all the states from &lt;a href='http://www.martinfowler.com/dslwip/Intro.html#ProgrammingMissGrantsController'&gt;Miss Grant&amp;#8217;s controller&lt;/a&gt; example are added, states declaration will look like this:&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S3fw76NkXiI/AAAAAAAAASA/RLd1IyIJm-k/s320/MF_stateMachine+-+MF_stateMachine.sandbox.sandbox_Miss+Grant+-+JetBrains+MPS+1.1+-1.jpg' border='0' /&gt;&lt;p&gt;Unfortunately, some of the states don&amp;#8217;t have any actions and empty actions statements add noise. Let&amp;#8217;s add condition to hide actions statement if there are no actions to show.&lt;/p&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3fxE_U3X0I/AAAAAAAAASI/JGR7YXctdtk/s640/Inspector.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fGtsl2UNI/AAAAAAAAAO4/rswOdzo6Oso/s400/generation.jpg' border='0' /&gt;&lt;p&gt;After language generation all empty actions are gone:&lt;/p&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fxkMfojKI/AAAAAAAAASQ/af8ardO0qiQ/s320/MF_stateMachine+-+MF_stateMachine.sandbox.sandbox_Miss+Grant+-+JetBrains+MPS+1.1+-3.jpg' border='0' /&gt;&lt;p&gt;This creates another problem. When new state is added, it doesn&amp;#8217;t have any actions. Because of that actions statement is not shown and there is no way to add new actions. This is one of the downsides of editing AST directly. There is a good solution, though. We can use &lt;strong&gt;intention&lt;/strong&gt; which will add empty actions.&lt;/p&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3fx7FwGKdI/AAAAAAAAASY/apZea3EF-vY/s400/MPS-6.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S3fx9i5d66I/AAAAAAAAASg/pULbgfCrvVw/s640/MPS-7.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S3fyNW82xfI/AAAAAAAAASo/3LsuZHhetOo/s320/MF_stateMachine+-+MF_stateMachine.intentions_%3Cno+name%3E%5BIntentionDeclaration%5D+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fyQIzBQNI/AAAAAAAAASw/CmpYyXgURNM/s400/MF_stateMachine+-+MF_stateMachine.intentions_AddAction+-+JetBrains+MPS+1.1+-1.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/S3fGtsl2UNI/AAAAAAAAAO4/rswOdzo6Oso/s400/generation.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fyfZlEBVI/AAAAAAAAAS4/kL5ntS6SnK0/s320/System.jpg' border='0' /&gt;&lt;h1 id='syntax_highlighting'&gt;Syntax highlighting&lt;/h1&gt;&lt;p&gt;The last thing that&amp;#8217;s left is syntax highlighting. It can be easily done with stylesheets. (Note that stylesheets are created in editor module.)&lt;/p&gt;&lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fzDbYcuGI/AAAAAAAAATA/x2L2YdswO64/s640/MPS-5.jpg' border='0' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/S3f0RiZMpvI/AAAAAAAAATI/pmmeaDn4FlQ/s320/MF_stateMachine+-+MF_stateMachine.editor_StateMachine+-+JetBrains+MPS+1.1+.jpg' border='0' /&gt;&lt;p&gt;Now we can use this stylesheet in editors to attach different styles to different parts of state machine language.&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S3f0a1nExkI/AAAAAAAAATY/Ce7AhdXqYbo/s640/Inspector-1-1.jpg' border='0' /&gt;&lt;p&gt;After applying styles to all editors, the final result will look like this:&lt;/p&gt;&lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/S3f0XWyG2iI/AAAAAAAAATQ/MvmOm5J8ARA/s400/MF_stateMachine+-+MF_stateMachine.sandbox.sandbox_Miss+Grant+-+JetBrains+MPS+1.1+-4.jpg' border='0' /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-1776518832406579575?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=3aHL8ZKQZmo:wfBGdrNrw6Q:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=3aHL8ZKQZmo:wfBGdrNrw6Q:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=3aHL8ZKQZmo:wfBGdrNrw6Q:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=3aHL8ZKQZmo:wfBGdrNrw6Q:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=3aHL8ZKQZmo:wfBGdrNrw6Q:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=3aHL8ZKQZmo:wfBGdrNrw6Q:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=3aHL8ZKQZmo:wfBGdrNrw6Q:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=3aHL8ZKQZmo:wfBGdrNrw6Q:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/3aHL8ZKQZmo" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-15T13:42:52.521-08:00</app:edited><media:thumbnail url="http://3.bp.blogspot.com/_VrU0ZHx_ziY/S3fDgfN0j6I/AAAAAAAAANo/wsHDnN6k0n4/s72-c/Pasted+Graphic+2.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2010/02/martin-fowlers-state-machine-in-mps.html</feedburner:origLink></item><item><title>Books I read (2009, 2008)</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/dSF1X7-DjhM/books-i-read-2009-2008.html</link><category>books</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Mon, 08 Feb 2010 13:13:21 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-7644552088181443578</guid><description>&lt;span style="font-family: verdana; font-size: 100%;"&gt;Recently I was thinking about which book to read next and came up with idea to make a list of books I've read over the last two years to understand where I'm now, where I'm heading to and may be read some of them again.&lt;/span&gt;  &lt;span style="font-family: verdana; font-size: 100%;"&gt;  &lt;br /&gt;
&lt;br /&gt;
I hope you can find something interesting in this list. (Books I considered not related to software development are excluded.)&lt;/span&gt;  &lt;br /&gt;
&lt;br /&gt;
&lt;h3 style="font-family: verdana; text-align: justify;"&gt;&lt;span style="font-size: 100%;"&gt;2009&lt;/span&gt;&lt;/h3&gt;&lt;div style="font-family: verdana;"&gt;&lt;/div&gt;&lt;ul style="font-family: verdana; text-align: justify;"&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;span class="external-link" style="font-weight: bold;"&gt;[!!] &lt;/span&gt;&lt;a class="external-link" href="http://www.madetostick.com/thebook/" rel="nofollow" style="font-weight: bold;"&gt;Made to stick&lt;/a&gt;&lt;span class="external-link"&gt; - why nobody remember company mission statement right after they hear it, but everyone know&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 100%;"&gt;&lt;span class="external-link"&gt; urban legends? It's a very practical book telling &lt;span style="font-weight: bold;"&gt;why&lt;/span&gt; it happens and &lt;span style="font-weight: bold;"&gt;how&lt;/span&gt; to make you ideas spread. &lt;span style="font-weight: bold;"&gt;The book of the year.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;span class="external-link"&gt;&lt;span style="font-weight: bold;"&gt;[!]&lt;/span&gt; &lt;/span&gt;&lt;a class="external-link" href="http://pragprog.com/titles/ahptl/pragmatic-thinking-and-learning" rel="nofollow" style="font-weight: bold;"&gt;Refactor your wetware&lt;/a&gt;&lt;span class="external-link"&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;- great collection of ideas about how to improve and rewire your mind. Contains &lt;span style="font-weight: bold;"&gt;a lot&lt;/span&gt; of interesting references to other books. &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 100%;"&gt;&lt;span class="external-link"&gt;Can be a life-changing book! &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/exec/obidos/ASIN/0789723107/" rel="nofollow"&gt;Don't make me think&lt;/a&gt;&lt;span class="external-link"&gt; - web usability 101. Awesome reading. Nice pictures.  I wish I had read this book years ago.&lt;/span&gt;&lt;a class="external-link" href="http://www.amazon.com/exec/obidos/ASIN/0789723107/" rel="nofollow"&gt; &lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Presentation-Zen-Simple-Design-Delivery/dp/0321525655" rel="nofollow"&gt;Presentation Zen&lt;/a&gt;&lt;span class="external-link"&gt; - make presentations like Steve Jobs :) It's real.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215" rel="nofollow"&gt;Domain Driven Design&lt;/a&gt;&lt;span class="external-link"&gt; - software design as it should be. &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Refactoring-Patterns-Joshua-Kerievsky/dp/0321213351" rel="nofollow"&gt;Refactoring to patterns&lt;/a&gt;&lt;span class="external-link"&gt; - the name says everything. Refactoring + patterns.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Real-World-Haskell-Bryan-OSullivan/dp/0596514980" rel="nofollow"&gt;Real World Haskell&lt;/a&gt; - hands-on book about Haskell. I haven't finished it though :( &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/User-Stories-Applied-Software-Development/dp/0321205685" rel="nofollow"&gt;User stories applied&lt;/a&gt;&lt;span class="external-link"&gt; - a guide how to use user stories in XP and Scrum.&lt;/span&gt;&lt;a class="external-link" href="http://www.amazon.com/User-Stories-Applied-Software-Development/dp/0321205685" rel="nofollow"&gt; &lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://pragprog.com/titles/jrpm/manage-it" rel="nofollow"&gt;Manage it!&lt;/a&gt;&lt;span class="external-link"&gt; - practical agile project management.&lt;/span&gt;&lt;a class="external-link" href="http://pragprog.com/titles/jrpm/manage-it" rel="nofollow"&gt; &lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Humane-Interface-Directions-Designing-Interactive/dp/0201379376" rel="nofollow"&gt;The Humane Interface&lt;/a&gt;&lt;span class="external-link"&gt; - interesting and sometimes surprising view on human interaction with computer interfaces.&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="external-link"&gt;&lt;/span&gt;&lt;a class="external-link" href="http://www.amazon.com/Humane-Interface-Directions-Designing-Interactive/dp/0201379376" rel="nofollow"&gt; &lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.co.uk/Developing-Multi-agent-Systems-Wiley-Technology/dp/0470057475" rel="nofollow"&gt;Developing Multi-agent Systems with JADE&lt;/a&gt;&lt;span class="external-link"&gt; - makes sense to read only if you like multi-agents or use JADE.&lt;/span&gt;&lt;a class="external-link" href="http://www.amazon.co.uk/Developing-Multi-agent-Systems-Wiley-Technology/dp/0470057475" rel="nofollow"&gt; &lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="font-family: verdana; text-align: justify;"&gt;&lt;/div&gt;&lt;h3 style="font-family: verdana; text-align: justify;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;a href="" name="BooksIread-2008"&gt;&lt;/a&gt;2008&lt;/span&gt;&lt;/h3&gt;&lt;div style="font-family: verdana; text-align: justify;"&gt;&lt;/div&gt;&lt;ul style="font-family: verdana; text-align: justify;"&gt;&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;span class="external-link" style="font-weight: bold;"&gt;[!!] &lt;/span&gt;&lt;a class="external-link" href="http://www.pragprog.com/titles/cfcar2/the-passionate-programmer" rel="nofollow"&gt;&lt;span style="font-weight: bold;"&gt;My job went to India&lt;/span&gt; (was renamed to &lt;span style="font-weight: bold;"&gt;The Passionate Programmer&lt;/span&gt;)&lt;/a&gt;&lt;span class="external-link"&gt; - very honest and realistic view on programming. Nothing about coding, only real-life pieces of advice. This is like &lt;a href="http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X"&gt;The Pragmatic Programmer&lt;/a&gt; 2nd no-technology-edition.  &lt;span style="font-weight: bold;"&gt;The book of the year.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;span class="external-link" style="font-weight: bold;"&gt;[!] &lt;/span&gt;&lt;a class="external-link" href="http://gettingreal.37signals.com/" rel="nofollow" style="font-weight: bold;"&gt;Getting real&lt;/a&gt;&lt;span class="external-link"&gt; - concise and opinionated book about web development and software development in general. It's awesome. It's free and available online in HTML format. &lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Ruby-Way-Second-Techniques-Programming/dp/0672328844" rel="nofollow"&gt;Ruby Way&lt;/a&gt;&lt;span class="external-link"&gt; - my favorite &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 100%;"&gt;&lt;span class="external-link"&gt;ruby &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 100%;"&gt;&lt;span class="external-link"&gt;cook-book. I still read it every now and then.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683" rel="nofollow"&gt;Effective Java 2nd edition&lt;/a&gt;&lt;span class="external-link"&gt; - a must-to-read book for every java developer. (Even if you've read 1st edition.)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Analysis-Patterns-Reusable-Object-Models/dp/0201895420" rel="nofollow"&gt;Implementation patterns&lt;/a&gt;&lt;span class="external-link"&gt; - for me it's a bit unusual, but very interesting view on programming.  Kent Beck can always take ordinary things and turn them around. This is &lt;a href="http://www.amazon.com/Smalltalk-Best-Practice-Patterns-Kent/dp/013476904X"&gt;Small Talk Best Practices&lt;/a&gt; rewritten for java.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Analysis-Patterns-Reusable-Object-Models/dp/0201895420" rel="nofollow"&gt;Analysis patterns&lt;/a&gt;&lt;span class="external-link"&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 100%;"&gt;&lt;span class="external-link"&gt; code is not the only thing you can reuse. Conceptual models might be more appropriate. Martin Fowler's first book. I'm a fan.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882" rel="nofollow"&gt;Clean code&lt;/a&gt;&lt;span class="external-link"&gt; - you should really care about your code. &lt;a href="http://www.amazon.com/Agile-Principles-Patterns-Practices-C/dp/0131857258"&gt;Agile Principles, Patterns, Practices&lt;/a&gt; was better, though.&lt;/span&gt;&lt;a class="external-link" href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882" rel="nofollow"&gt; &lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.pragprog.com/titles/mnee/release-it" rel="nofollow"&gt;Release it!&lt;/a&gt;&lt;span class="external-link"&gt; - real-life description how to create web applications which don't fail after going into production. (This book is focused on java.)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.pragprog.com/titles/svn/pragmatic-version-control-using-subversion" rel="nofollow"&gt;Pragmatic SVN&lt;/a&gt;&lt;span class="external-link"&gt; - &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 100%;"&gt;&lt;span class="external-link"&gt;concise and &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 100%;"&gt;&lt;span class="external-link"&gt;pragmatic guide to SVN.&lt;/span&gt;&lt;a class="external-link" href="http://www.pragprog.com/titles/svn/pragmatic-version-control-using-subversion" rel="nofollow"&gt; &lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Become-Highly-Paid-Corporate-Programmer/dp/158347045X" rel="nofollow"&gt;How to become a highly paid corporate programmer&lt;/a&gt;&lt;span class="external-link"&gt; - controversial book. I didn't agree with a lot of things. That's why I kept reading.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.infoq.com/minibooks/scrum-xp-from-the-trenches" rel="nofollow"&gt;Scrum and XP from the trenches&lt;/a&gt;&lt;span class="external-link"&gt; - real-life view on Scrum. Concise and easy to read. It's free to download from infoq.com.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Guide-Project-Management-Knowledge-PMBOK/dp/1880410230" rel="nofollow"&gt;A Guide to the PMBOK&lt;/a&gt;&lt;span class="external-link"&gt; - "old-school" ideas about management. Boring to read but very useful.&lt;/span&gt;&lt;a class="external-link" href="http://www.amazon.com/Guide-Project-Management-Knowledge-PMBOK/dp/1880410230" rel="nofollow"&gt; &lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: 100%;"&gt;&lt;a class="external-link" href="http://www.amazon.com/Black-Swan-Impact-Highly-Improbable/dp/1400063515" rel="nofollow"&gt;Black swan&lt;/a&gt;&lt;span class="external-link"&gt; - accept that there are unknowns you don't know about. Models we use to predict future will never really work. This is pragmatic nihilism.&lt;/span&gt;&lt;a class="external-link" href="http://www.amazon.com/Black-Swan-Impact-Highly-Improbable/dp/1400063515" rel="nofollow"&gt; &lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="font-family: verdana; text-align: justify;"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-7644552088181443578?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=dSF1X7-DjhM:Tne7xpVRNbE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=dSF1X7-DjhM:Tne7xpVRNbE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=dSF1X7-DjhM:Tne7xpVRNbE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=dSF1X7-DjhM:Tne7xpVRNbE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=dSF1X7-DjhM:Tne7xpVRNbE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=dSF1X7-DjhM:Tne7xpVRNbE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=dSF1X7-DjhM:Tne7xpVRNbE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=dSF1X7-DjhM:Tne7xpVRNbE:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/dSF1X7-DjhM" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-08T13:13:21.416-08:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2010/02/books-i-read-2009-2008.html</feedburner:origLink></item><item><title>Win + key shortcuts in IntelliJ</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/Ig-r5ncWyI4/i-always-thought-its-not-possible-to.html</link><category>intellij</category><category>shortcuts</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Mon, 15 Feb 2010 13:35:40 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-5265221432930440636</guid><description>&lt;span style="font-family: verdana; font-size: 100%;"&gt;I always thought it’s not possible to assign Win + key shortcuts in IntelliJ.  The reason was that if you press Win + key &lt;/span&gt;&lt;span style="font-family: verdana; font-size: 100%;"&gt;in shortcut editor, you see something like this:&lt;/span&gt;    &lt;br /&gt;
&lt;div class="MsoPlainText" style="color: black; font-family: verdana;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="color: black; font-family: verdana;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;a href="http://1.bp.blogspot.com/_VrU0ZHx_ziY/S2xlpJH22DI/AAAAAAAAANY/Ii2PRPbPsxo/s1600-h/image002.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5434830607827261490" src="http://1.bp.blogspot.com/_VrU0ZHx_ziY/S2xlpJH22DI/AAAAAAAAANY/Ii2PRPbPsxo/s400/image002.jpg" style="cursor: pointer; display: block; height: 371px; margin: 0px auto 10px; text-align: center; width: 294px;" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoPlainText" style="color: black; font-family: verdana;"&gt;&lt;span style="font-size: 100%;"&gt;It looks very much like IntelliJ cannot use this kind of shortcuts. Turns out it can!&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoPlainText" style="color: black; font-family: verdana;"&gt;&lt;span style="font-size: 100%;"&gt;The trick is to use Win button as a first key-stroke and key as a second one. Surprisingly enough it works when Win + key are pressed simultaneously.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoPlainText" style="color: black; font-family: verdana;"&gt;&lt;a href="http://4.bp.blogspot.com/_VrU0ZHx_ziY/S2xmD1r6TDI/AAAAAAAAANg/7LVIX68hBAw/s1600-h/image003.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5434831066466241586" src="http://4.bp.blogspot.com/_VrU0ZHx_ziY/S2xmD1r6TDI/AAAAAAAAANg/7LVIX68hBAw/s400/image003.jpg" style="cursor: pointer; display: block; height: 321px; margin: 0px auto 10px; text-align: center; width: 400px;" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoPlainText" style="color: black; font-family: verdana;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoPlainText" style="color: black; font-family: verdana;"&gt;&lt;span style="font-size: 100%;"&gt;(In the above picture I assign Win + S shortcut to split editor. I love left-handed shortcuts which easy to use :))&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoPlainText" style="color: black; font-family: verdana;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoPlainText" style="color: black; font-family: verdana;"&gt;&lt;span style="font-size: 100%;"&gt;I’ve only tried it in Windows XP. Would be nice if it also works in &lt;st1:place st="on"&gt;Vista&lt;/st1:place&gt; and Windows 7.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoPlainText" face="verdana" style="color: black;"&gt;&lt;span style="font-size: 100%;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-5265221432930440636?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=Ig-r5ncWyI4:TkC1CNNJXMs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=Ig-r5ncWyI4:TkC1CNNJXMs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=Ig-r5ncWyI4:TkC1CNNJXMs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=Ig-r5ncWyI4:TkC1CNNJXMs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=Ig-r5ncWyI4:TkC1CNNJXMs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=Ig-r5ncWyI4:TkC1CNNJXMs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=Ig-r5ncWyI4:TkC1CNNJXMs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=Ig-r5ncWyI4:TkC1CNNJXMs:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/Ig-r5ncWyI4" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-15T13:35:40.923-08:00</app:edited><media:thumbnail url="http://1.bp.blogspot.com/_VrU0ZHx_ziY/S2xlpJH22DI/AAAAAAAAANY/Ii2PRPbPsxo/s72-c/image002.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2010/02/i-always-thought-its-not-possible-to.html</feedburner:origLink></item><item><title>Design Limits</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/dzriYrUAFOc/design-limits.html</link><category>software development</category><category>design</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Mon, 23 Nov 2009 08:04:12 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-6110371068453517630</guid><description>"A lot" doesn't mean "good" even there is a lot of something good. You should know when to stop.
&lt;p/&gt;
One of the worst thing I've ever done as a developer is over-designing. I've overdone many other things too, but over-designing is probably the number one. Like many other words the word "design" is overloaded. In software development world it usually means a structure of classes or the process of creating this structure. For example, &lt;a href="http://martinfowler.com/bliki/DesignPayoffLine.html"&gt;Design Payoff&lt;/a&gt; (from Martin Fowler's &lt;a href="http://martinfowler.com/bliki/DesignStaminaHypothesis.html]"&gt;Design Stamina Hypothesis&lt;/a&gt;) has always meant for me that "if you have a good structure, you will be able implement a lot of stuff; if you have no structure, you're out of luck".

&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 618px; height: 329px;" src="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SwRi-KflgSI/AAAAAAAAAM8/d8FtdHQnvoA/s1600/designStaminaGraph.gif.png" border="0" alt=""id="Design payoff line" /&gt;

I can't say for sure whether this diagram implies "design" not only as structure but also as activity. Probably, the main point of it is just "payoff line". If you redraw this diagram in terms of "features per iteration", you will get something like this.

&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 600px; height: 276px;" src="http://3.bp.blogspot.com/_VrU0ZHx_ziY/SwRi-K5E1JI/AAAAAAAAANE/33eG2hnwIcM/s1600/designStaminaGraph2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5405554272966595730" /&gt;


From this diagram it's easy to see that the amount of features you can implement with "good design" is &lt;span style="font-weight:bold;"&gt;limited&lt;/span&gt;. This is kind of obvious thing which, probably, every developer knows very well from he's own experience.

"Design" as the process of creating "design structure" comes to play every time you want to implement something which turns out to be cumbersome or very hard to do with current design. This is what I blame myself most of all. First off, it's the amount of time spent redesigning. I do not claim it to be true, but thinking about last several months for me the following dependency seems to close to reality.

&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 600px; height: 276px;" src="http://2.bp.blogspot.com/_VrU0ZHx_ziY/SwRi-Req4vI/AAAAAAAAANM/oWOlnZIK0Bw/s1600/mpoint.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5405554274734891762" /&gt;

After a certain point the harder you try to "improve" design, the worst result you get. In other words, there is also a &lt;b&gt;limit&lt;/b&gt; of much effort it's worth spending on design. The worst part of it is that determining how close you're to "masturbation point" is always a judgment call. Basically you don't know where you are on the curve. Even when you feel you've crossed the point, there is always temptation instead of &lt;a href="http://blog.jayfields.com/2009/03/kill-your-darlings.html"&gt;Killing Your Darlings&lt;/a&gt; to continue in hope of getting some insight and turning things right. Spending more time redesigning something doesn't necessarily mean that design becomes more complicated. It can become simpler but less appropriate. It's also true that the time you spend designing is the time you could've spent adding new feature. The only good way I found to avoid this is to add feature with minimal changes and then consciously &lt;b&gt;experiment&lt;/b&gt; with design ideas. Or &lt;a href="http://www.threeriversinstitute.org/blog/?p=374"&gt;just wait&lt;/a&gt;.
&lt;p/&gt;
&lt;a href="http://weblogs.java.net/blog/82/2003/09/02/aristotles-error-or-agile-smagile"&gt;Going meta&lt;/a&gt;, this can be applied to other areas like code conventions, static code analysis or &lt;a href="http://www.headwaysoftware.com/products/structure101/index.php"&gt;static dependencies rules&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-6110371068453517630?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=dzriYrUAFOc:cW8EXeGVAcE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=dzriYrUAFOc:cW8EXeGVAcE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=dzriYrUAFOc:cW8EXeGVAcE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=dzriYrUAFOc:cW8EXeGVAcE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=dzriYrUAFOc:cW8EXeGVAcE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=dzriYrUAFOc:cW8EXeGVAcE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=dzriYrUAFOc:cW8EXeGVAcE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=dzriYrUAFOc:cW8EXeGVAcE:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/dzriYrUAFOc" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-23T08:04:12.285-08:00</app:edited><media:thumbnail url="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SwRi-KflgSI/AAAAAAAAAM8/d8FtdHQnvoA/s72-c/designStaminaGraph.gif.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2009/11/design-limits.html</feedburner:origLink></item><item><title>Slides from "DSL explained" presentation</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/jdBVJYtrLxE/slides-from-dsl-explained-presentation.html</link><category>mps</category><category>dsl</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Sun, 08 Nov 2009 07:21:22 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-1270634682735037451</guid><description>&lt;div style="width: 425px; text-align: left;" id="__ss_2450024"&gt;&lt;object style="margin: 0px;" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=dsl-091108083729-phpapp02&amp;amp;stripped_title=dsl-explained-2450024"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=dsl-091108083729-phpapp02&amp;amp;stripped_title=dsl-explained-2450024" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size: 11px; font-family: tahoma,arial; height: 26px; padding-top: 2px;"&gt;View more &lt;a style="text-decoration: underline;" href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a style="text-decoration: underline;" href="http://www.slideshare.net/dkandalov"&gt;dkandalov&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-1270634682735037451?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=jdBVJYtrLxE:CvbpVM8t1Kw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=jdBVJYtrLxE:CvbpVM8t1Kw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=jdBVJYtrLxE:CvbpVM8t1Kw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=jdBVJYtrLxE:CvbpVM8t1Kw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=jdBVJYtrLxE:CvbpVM8t1Kw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=jdBVJYtrLxE:CvbpVM8t1Kw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=jdBVJYtrLxE:CvbpVM8t1Kw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=jdBVJYtrLxE:CvbpVM8t1Kw:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/jdBVJYtrLxE" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-08T07:21:22.517-08:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><enclosure url="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=dsl-091108083729-phpapp02&amp;amp;stripped_title=dsl-explained-2450024" length="121655" type="application/x-shockwave-flash" /><media:content url="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=dsl-091108083729-phpapp02&amp;amp;stripped_title=dsl-explained-2450024" fileSize="121655" type="application/x-shockwave-flash" /><feedburner:origLink>http://codingmatters.blogspot.com/2009/11/slides-from-dsl-explained-presentation.html</feedburner:origLink></item><item><title>IntelliJ good intentions screencast</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/jpKeK-9adCE/intellij-good-intentions-screencast.html</link><category>java</category><category>intellij</category><category>tips</category><category>screencast</category><category>kata</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Wed, 04 Nov 2009 04:41:01 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-7339965961676632093</guid><description>&lt;p&gt;Here is the screencast where I show IntelliJ some tricks (mostly intentions) while doing &lt;a
        href='http://codekata.pragprog.com/2007/01/kata_four_data_.html'&gt;kata 4&lt;/a&gt;. This is a rough version. I would
    never think that creating 20 minutes screencast can take so much effort. Actually, I stopped at some point and
    focused on delivering it. In other words I&amp;#8217;m not satisfied with how this screencast looks. But putting even
    more efforts in it without feedback is even worse. Therefore, &lt;em&gt;I would very much appreciate any kind of
        feedback&lt;/em&gt;. (&amp;#8220;It sucks, don&amp;#8217;t ever do it again&amp;#8221; kind of feedback is acceptable :) but I
    would prefer it said in a less direct way.)&lt;/p&gt;
&lt;object height='385' width='480'&gt;
    &lt;param name='movie' value='http://www.youtube.com/p/E713ECE6865AF6EE&amp;hl=en&amp;fs=1&amp;hd=1'/&gt;
    &lt;param name='allowFullScreen' value='true'/&gt;
    &lt;param name='allowscriptaccess' value='always'/&gt;
    &lt;embed src='http://www.youtube.com/p/E713ECE6865AF6EE&amp;hl=en&amp;fs=1&amp;hd=1' allowfullscreen='true'
           type='application/x-shockwave-flash' allowscriptaccess='always' height='385' width='480'&gt;&lt;/embed&gt;
&lt;/object&gt;&lt;p&gt;Technical details:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;video captured with &lt;a href='http://camstudio.org/'&gt;CamStudio&lt;/a&gt;;&lt;/li&gt;
    &lt;li&gt;video editing done with &lt;a href='http://www.virtualdub.org/'&gt;VirtualDub&lt;/a&gt;;&lt;/li&gt;
    &lt;li&gt;audio recorded and processed with &lt;a href='http://audacity.sourceforge.net/'&gt;Audacity&lt;/a&gt;;&lt;/li&gt;
    &lt;li&gt;on-screen keyboard is &lt;a href='http://www.comfort-software.com/on-screen-keyboard.html'&gt;Comfort On-Screen
        Keyboard&lt;/a&gt; (trial version; it&amp;#8217;s not free).
    &lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-7339965961676632093?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=jpKeK-9adCE:duoNSnRQSP8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=jpKeK-9adCE:duoNSnRQSP8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=jpKeK-9adCE:duoNSnRQSP8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=jpKeK-9adCE:duoNSnRQSP8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=jpKeK-9adCE:duoNSnRQSP8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=jpKeK-9adCE:duoNSnRQSP8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=jpKeK-9adCE:duoNSnRQSP8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=jpKeK-9adCE:duoNSnRQSP8:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/jpKeK-9adCE" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-04T04:41:01.670-08:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><enclosure url="http://www.youtube.com/p/E713ECE6865AF6EE&amp;hl=en&amp;fs=1&amp;hd=1" length="905" type="application/x-shockwave-flash" /><media:content url="http://www.youtube.com/p/E713ECE6865AF6EE&amp;hl=en&amp;fs=1&amp;hd=1" fileSize="905" type="application/x-shockwave-flash" /><feedburner:origLink>http://codingmatters.blogspot.com/2009/11/intellij-good-intentions-screencast.html</feedburner:origLink></item><item><title>Code formatting vs TDD</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/32b-e2ABKww/code-formatting-vs-tdd.html</link><category>psychology</category><category>methodology</category><category>tdd</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Mon, 26 Oct 2009 01:08:48 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-4422182976530430434</guid><description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_VrU0ZHx_ziY/St-BZae6_SI/AAAAAAAAAMc/oEZ02IFD3nQ/s1600-h/CMS_Star.JPG"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 330px; height: 339px;" src="http://1.bp.blogspot.com/_VrU0ZHx_ziY/St-BZae6_SI/AAAAAAAAAMc/oEZ02IFD3nQ/s400/CMS_Star.JPG" alt="" id="BLOGGER_PHOTO_ID_5395173152218873122" border="0" /&gt;&lt;/a&gt;If you are a professional programmer, I'm pretty sure that you format your code. But could you convince someone who doesn't to do so? Not force, but make the person believe it's the right thing to do. &lt;p user="true" style="display: none;" mce_style="display:none"&gt;
&lt;/p&gt; &lt;p user="true" style="display: none;" mce_style="display:none"&gt;
&lt;/p&gt; &lt;p user="true" style="display: none;" mce_style="display:none"&gt;
&lt;/p&gt; &lt;p&gt;A while ago I was lucky to participate in a team-building game called "&lt;a href="http://www.eaglesflight.com/pa-conference-programs.php?p=31" mce_href="http://www.eaglesflight.com/pa-conference-programs.php?p=31" rel="nofollow" linktype="raw" wikidestination="http://www.eaglesflight.com/pa-conference-programs.php?p=31" aliasspecified="true"&gt;Council of the Marble Star&lt;/a&gt;". In this game you are divided in several teams. Each team has a certain amount of resources (like triangle and square pieces skin) and several cards with rules (like "after the first round teams will get 10 points for each square they own"). At the end of the game all the teams which have more than say 1000 points win, other teams lose. There are no other rules. You can trade your resources and information with other teams in any way you want. I played similar games before and knew that there are enough points for all teams to win. The only real problem for teams is to trust each other and &lt;b&gt;share information&lt;/b&gt;. If no one shares, few teams win. If everyone shares, everybody win. There was another guy in the same team who also knew it. Given that, our team strategy was to convince others to share information so that everybody could win. We don't trade. We publish all our information for free. We tell people everything we know. Guess what happened. We lost. As well as several other teams. Why?! From the very beginning we knew how this game works. People we were trying to convince were co-workers, not strangers. It was just a game, not a matter of life and death. And still we failed to convince other teams to do the right thing. (In case I get into marketing one day and HR manager reads this... I learned the lesson, I can do much better now! I'll tell "how" on interview :))&lt;/p&gt; &lt;p user="true" style="display: none;" mce_style="display:none"&gt;
&lt;/p&gt;  &lt;p user="true" style="display: none;" mce_style="display:none"&gt;
&lt;/p&gt; &lt;p user="true" style="display: none;" mce_style="display:none"&gt;
&lt;/p&gt; &lt;p&gt;While this is a funny story, it's not about programming.&lt;/p&gt; &lt;p user="true" style="display: none;" mce_style="display:none"&gt;
&lt;/p&gt; &lt;p&gt;Here is another story about programming. I was sitting next to my younger brother writing his first real-world program. ARP ping in C for Linux is a pretty cool start, isn't it? The program wasn't big. Just command-line arguments handling, scanning network in the same thread and printing results. The program worked fine. The only problem was that he did &lt;b&gt;not&lt;/b&gt; use indentation. Ok, it was a "problem" from my point of view. Everything works, he understands code. Where is the problem? Why should he care that every piece of C code he can find on Internet has indentation? I think, it is not necessary to say that I failed to convince him to use indentation. (As a side note, he used a lot of procedures and no nested ifs, so the code didn't look bad.)&lt;/p&gt; &lt;p user="true" style="display: none;" mce_style="display:none"&gt;
&lt;/p&gt; &lt;p user="true" style="display: none;" mce_style="display:none"&gt;
&lt;/p&gt; &lt;p&gt;Can it be that there is something similar happening with other arguments? You know you're right, but you just cannot effectively communicate that. If it's the case, for me the first one on the list is TDD, followed by other XP and agile practices. It's true that the fact that you can't persuade someone to do X, doesn't make X a good thing. I know there are always new problems with the solutions which are supposed to solve your old problems. On the other hand, how do you know where is the line between obvious and not so obvious, line indentation and TDD? I'm serious. If I don't have lots of nested structures, if I can understand what I'm doing, all this code formatting stuff is just a waste of time.&lt;/p&gt; &lt;p user="true" style="display: none;" mce_style="display:none"&gt;
&lt;/p&gt; &lt;p user="true" style="display: none;" mce_style="display:none"&gt;
&lt;/p&gt; &lt;p user="true" style="display: none;" mce_style="display:none"&gt;
&lt;/p&gt; &lt;p&gt;Note to myself: read "&lt;a href="http://www.amazon.com/Fearless-Change-Patterns-Introducing-Ideas/dp/0201741571" mce_href="http://www.amazon.com/Fearless-Change-Patterns-Introducing-Ideas/dp/0201741571" rel="nofollow" linktype="raw" wikidestination="http://www.amazon.com/Fearless-Change-Patterns-Introducing-Ideas/dp/0201741571" aliasspecified="true"&gt;Fearless change&lt;/a&gt;"  &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-4422182976530430434?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=32b-e2ABKww:vL2raGPbvrw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=32b-e2ABKww:vL2raGPbvrw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=32b-e2ABKww:vL2raGPbvrw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=32b-e2ABKww:vL2raGPbvrw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=32b-e2ABKww:vL2raGPbvrw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=32b-e2ABKww:vL2raGPbvrw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=32b-e2ABKww:vL2raGPbvrw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=32b-e2ABKww:vL2raGPbvrw:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/32b-e2ABKww" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-26T01:08:48.750-07:00</app:edited><media:thumbnail url="http://1.bp.blogspot.com/_VrU0ZHx_ziY/St-BZae6_SI/AAAAAAAAAMc/oEZ02IFD3nQ/s72-c/CMS_Star.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2009/10/code-formatting-vs-tdd.html</feedburner:origLink></item><item><title>Zen Programming</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/_740BKtYbQ0/zen-programming.html</link><category>software development</category><category>methodology</category><category>zen</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Wed, 21 Oct 2009 15:07:32 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-2861519223822884147</guid><description>&lt;p&gt;Are you tired of moving methods around to “improve” design? Are you tired of trying to understand other developers’ code? Are you struggling to learn IDE shortcuts? Don’t know what to do with automated refactorings in “Refactor” menu? There is good news, you don’t need it all. Acknowledge the true nature of software. The only thing you need is to know the problem you’re solving and write code.&lt;/p&gt;&lt;p&gt;I knew I was out of place from the very beginning. I started the application and after splash screen it displayed an error. “What’s is wrong with it?” I asked another developer. “It’s ok. Just try starting it several more times, and it will work,” he said. I was, and still am, proponent of technical practices which are often used under “agile” term. Almost everything in this place was contradictory to my believes. (I will omit non-technical problems.)&lt;/p&gt;&lt;ul&gt;&lt;li&gt;There was no up-to-date documentation and no one could cohesively explain what application does, what are the inputs and outputs. (I don’t mean no one knew, only that no one could explain.)&lt;/li&gt;&lt;li&gt;There was only one development environment shared between everyone. (To make the matters worse databases were located far away and application start-up time was more than 10 minutes.)&lt;/li&gt;&lt;li&gt;At times application won’t start at all for unapparent external reasons.&lt;/li&gt;&lt;li&gt;There was no dedicated build server.&lt;/li&gt;&lt;li&gt;There were no unit tests (existing ones were broken and abandoned long ago). The only meaning of the world “test” was to test things manually.&lt;/li&gt;&lt;li&gt;There were no full-time testers on the project.&lt;/li&gt;&lt;li&gt;There were a lot of classes with 1000 lines and more. Sometimes with mixed business logic, UI and inputs.&lt;/li&gt;&lt;li&gt;The worst thing was that no one cared about it. &lt;strong&gt;And there was a reason…&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;a href="http://farm1.static.flickr.com/76/226192476_087502685f.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://farm1.static.flickr.com/76/226192476_087502685f.jpg" alt="" style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 500px; height: 333px;" border="0" /&gt;&lt;/a&gt;&lt;p&gt;While my productivity sunk, most of other developers were making good constant progress. If application wouldn’t start, they would know which dependent-on services to restart and who could do it. They could test code manually in debugger and it would work just fine. They could make sense of huge piles of multi-threaded code by just stepping through it in debugger. They were not writing clean or perfect code. They were making mistakes sometimes, but non-critical ones). They were adding features in time and bringing business value in spite of everything.&lt;/p&gt;&lt;p&gt;It’s said “change your organization or change your organization”. I believe there is another option. You can learn what others are doing and do exactly that. This is what I’ve been trying to do over the last year. I called this “zen-programming” (name inspired by this &lt;a href="http://www.amazon.com/Zen-Programming-Geoffrey-James/dp/0931137098"&gt;book&lt;/a&gt;) and from my humble observation here is the most contradictory things Zen Programmers do.&lt;/p&gt;&lt;p&gt;You &lt;strong&gt;discard complicated tools&lt;/strong&gt;, because you don’t need them. They are distraction.&lt;/p&gt;&lt;p&gt;You &lt;strong&gt;don’t automate tasks&lt;/strong&gt;, because you can do them yourself fast enough.&lt;/p&gt;&lt;p&gt;You &lt;strong&gt;don’t write documentation&lt;/strong&gt;, because source code is the best and the only credible documentation.&lt;/p&gt;&lt;p&gt;You &lt;strong&gt;don’t pay much attention to your code&lt;/strong&gt; appearance, because the essence is not in how it looks, but how it works.&lt;/p&gt;&lt;p&gt;You &lt;strong&gt;don’t let code drive you&lt;/strong&gt;, because you’re the master of code. Beautiful cloud castles from code are waste of your time.&lt;/p&gt;&lt;p&gt;You &lt;strong&gt;never rely on UML-like pictures to explain a program&lt;/strong&gt;. They are inaccurate and misleading.&lt;/p&gt;&lt;p&gt;You are &lt;strong&gt;not afraid of duplication&lt;/strong&gt;, because you know well enough where it is.&lt;/p&gt;&lt;p&gt;You &lt;strong&gt;don’t spend time beatifying code&lt;/strong&gt; and making it easier to understand, you live in code, you know it too well.&lt;/p&gt;&lt;p&gt;When working with someone else’s code, you &lt;strong&gt;don’t think “why” you think “how”&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;You &lt;strong&gt;don’t need to double-check your ideas&lt;/strong&gt;, because you know you’re right. Even though your solution may not be perfect, it will work just fine. You totally trust yourself.&lt;/p&gt;&lt;p&gt;You &lt;strong&gt;never attempt to try create anything perfect&lt;/strong&gt;, because it costs too much and no one needs it. “Most useful” doesn’t mean “perfect” (far from this).&lt;/p&gt;&lt;p&gt;As a Zen Programmer you acknowledge messy and chaotic nature of software. You don’t struggle with it, but embrace it by becoming a part of it. While there is a value in well designed, thought through systems, code is not the purpose of software nor they reflect what software really is.&lt;/p&gt;&lt;p&gt;Update: what I meant by Zen Programmers seems similar to &lt;a href="http://www.joelonsoftware.com/items/2009/09/23.html"&gt;Duct Tape Programmers&lt;/a&gt; except that zen-guys are not in the least afraid of "C++, templates, multiple inheritance, multithreading".
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-2861519223822884147?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=_740BKtYbQ0:J4y6lr2WKKA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=_740BKtYbQ0:J4y6lr2WKKA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=_740BKtYbQ0:J4y6lr2WKKA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=_740BKtYbQ0:J4y6lr2WKKA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=_740BKtYbQ0:J4y6lr2WKKA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=_740BKtYbQ0:J4y6lr2WKKA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=_740BKtYbQ0:J4y6lr2WKKA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=_740BKtYbQ0:J4y6lr2WKKA:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/_740BKtYbQ0" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-21T15:07:32.651-07:00</app:edited><media:thumbnail url="http://farm1.static.flickr.com/76/226192476_087502685f_t.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">9</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2009/09/zen-programming.html</feedburner:origLink></item><item><title>Misc IntelliJ tips</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/agNDnxzSBx0/misc-intellij-tips.html</link><category>java</category><category>intellij</category><category>tips</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Wed, 18 Nov 2009 13:14:43 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-2827498988025141867</guid><description>&lt;p&gt;Here are miscellaneous IntelliJ tips. Some of them are very simple and yet took me a long time to discover. I hope you&amp;#8217;ll find something new and useful among them. But please be aware that while using cool IDE features can make your work easier and more fun &lt;strong&gt;there is a limit to which they can help&lt;/strong&gt;. After all, software development is not about using IDEs. &amp;#8220;Use a Single Editor Well&amp;#8221; is only one tip out of 70 in &lt;a href='http://www.pragprog.com/the-pragmatic-programmer/extracts/tips'&gt;pragmatic programmer tips&lt;/a&gt;. Be aware also of &lt;a href='http://www.codinghorror.com/blog/archives/000921.html'&gt;baby duck syndrome&lt;/a&gt; and try another editor or IDE. &lt;a href='http://www.gnu.org/software/emacs'&gt;Emacs&lt;/a&gt;, for example :)&lt;/p&gt;&lt;br /&gt;&lt;h3 id='debug'&gt;DEBUG&lt;/h3&gt;&lt;br /&gt;&lt;h4 id='when_debugging_you_can_see_variable_value_under_mouse_cursor_with_alt___left_button_click_'&gt;When debugging you can see variable value under mouse cursor with alt + &amp;lt; left button click &amp;gt;&lt;/h4&gt;&lt;p&gt;&amp;#8220;Alt + click&amp;#8221; can be more convenient compared to alternatives like pointing mouse on a variable, waiting for popup and then clicking on &amp;#8221;+&amp;#8221;. Not to mention selecting text and using &amp;#8220;Evaluate expression&amp;#8221; action. &amp;#8220;Alt + click&amp;#8221; fits well with &amp;#8220;browsing mode&amp;#8221; (left hand on keyboard, right with mouse).&lt;/p&gt;&lt;a href='http://4.bp.blogspot.com/_VrU0ZHx_ziY/SaWyiHj0qKI/AAAAAAAAAKs/Xq5C0jHdMRY/s1600-h/eval_in_debug.png' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;    &lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/SaWyiHj0qKI/AAAAAAAAAKs/Xq5C0jHdMRY/s400/eval_in_debug.png' border='0' id='BLOGGER_PHOTO_ID_5306844035140593826' alt='' style='display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 153px;' /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4 id='you_can_disable_breakpoint_with_alt___right_button_click_on_the_gutter_'&gt;You can disable breakpoint with alt + &amp;lt; right button click on the gutter &amp;gt;&lt;/h4&gt;&lt;p&gt;There isn&amp;#8217;t much to say about it, just a fast way to disable one or several breakpoints. To disable all breakpoints it&amp;#8217;s still easier to use &amp;#8220;Mute breakpoints&amp;#8221; in debug window.&lt;/p&gt;&lt;br /&gt;&lt;h4 id='you_can_create_tracing_breakpoint_with_shift___left_button_click_on_the_gutter_'&gt;You can create &amp;#8220;tracing breakpoint&amp;#8221; with shift + &amp;lt; left button click on the gutter &amp;gt;&lt;/h4&gt;&lt;p&gt;This is just a shortcut for adding a breakpoint and then configuring it. By default &amp;#8220;tracing breakpoint&amp;#8221; will have configuration like in the picture below.&lt;/p&gt;&lt;a href='http://1.bp.blogspot.com/_VrU0ZHx_ziY/SaW4i0ZKEzI/AAAAAAAAAK0/MpKLoVE9MCA/s1600-h/tracing_breakpoint.png' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;    &lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/SaW4i0ZKEzI/AAAAAAAAAK0/MpKLoVE9MCA/s400/tracing_breakpoint.png' border='0' id='BLOGGER_PHOTO_ID_5306850644245222194' alt='' style='display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 143px;' /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4 id='its_easier_to_browse_external_stacktrace_with_stacktrace_analyzer_rather_than_navigate_to_lines_manually'&gt;It&amp;#8217;s easier to browse external stacktrace with stacktrace analyzer, rather than navigate to lines manually&lt;/h4&gt;&lt;p&gt;While writing I found that stacktrace analyzer has already been mentioned in several posts. See &lt;a href='http://www.jetbrains.com/idea/features/features.html#Thread_dump_analyzer'&gt;JetBrains&lt;/a&gt; &lt;a href='http://blogs.jetbrains.com/idea/2006/08/analyzing-external-stack-traces/'&gt;posts&lt;/a&gt; or &lt;a href='http://www.javalobby.org/java/forums/t73243.html'&gt;post on java lobby&lt;/a&gt;. There is also a nice feature in stacktrace analyzer that it takes content from system clipboard, so that you don&amp;#8217;t have to paste stacktrace in it manually. You select stacktrace in email (or where it is), copy it into clipboard, go to IntelliJ and press Alt+Z, S, Enter (I use menu :)).&lt;/p&gt;&lt;br /&gt;&lt;h4 id='if_you_want_to_find_exceptions_of_which_you_are_not_aware_consider_adding_exception_breakpoint'&gt;If you want to find exceptions of which you are not aware, consider adding exception breakpoint&lt;/h4&gt;&lt;p&gt;How well it will work depends very much on how exception are handled in your project. I found exception breakpoints useful while working on a project where the main pattern for handling exceptions is catching java.lang.Exception and writing stacktrace to log. You may silently get NPE and the only place to see it is the log file which has tons of other stuff. Moreover, you have to search log for exceptions manually. With breakpoint exceptions there is no way you wouldn&amp;#8217;t notice the problem.&lt;/p&gt;&lt;p&gt;More generally it may be a good idea to have NPE breakpoint and breakpoint for uncaught exceptions to spot problems right away. (IIRC this is what VisualStudio does.)&lt;/p&gt;&lt;a href='http://2.bp.blogspot.com/_VrU0ZHx_ziY/SaW5-fH5oZI/AAAAAAAAAK8/W6tJKUDlFuA/s1600-h/exception_breakpoint.png' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;    &lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/SaW5-fH5oZI/AAAAAAAAAK8/W6tJKUDlFuA/s400/exception_breakpoint.png' border='0' id='BLOGGER_PHOTO_ID_5306852219083661714' alt='' style='display:block; margin:0px auto 10px; text-align:center; cursor:pointer; cursor:hand;width: 400px; height: 165px;' /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4 id='if_you_debug_objects_which_form_a_tree_consider_using_custom_data_type_renderers'&gt;If you debug objects which form a tree, consider using custom data type renderers&lt;/h4&gt;&lt;p&gt;Basically, &amp;#8220;data type renderer&amp;#8221; is just a way to tell debugger what it should show and what should not. &lt;a href='http://blogs.jetbrains.com/idea/2008/04/type-renderers/'&gt;Here is&lt;/a&gt; post about type renderers in IntelliJ blog with more details. You can use type renderers for any type. I only found it useful to explore tree-like object structures. In particular to observe UI components hierarchy, &lt;a href='http://www.antlr.org'&gt;antlr&lt;/a&gt; AST and IntelliJ PSI trees. &lt;a href='http://2.bp.blogspot.com/_VrU0ZHx_ziY/Sa2L7-zDGJI/AAAAAAAAAL0/uGd04LZDxjs/s1600-h/psi_debug_config.png' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;    &lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/Sa2L7-zDGJI/AAAAAAAAAL0/uGd04LZDxjs/s400/psi_debug_config.png' border='0' id='BLOGGER_PHOTO_ID_5309053398325336210' alt='' style='display:block; margin:0px auto 10px; text-align:center; cursor:pointer; cursor:hand;width: 400px; height: 159px;' /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h4 id='if_you_debug_program_with_recursive_or_complicated_call_stack_consider_marking_instances_to_better_understand_it'&gt;If you debug program with recursive (or complicated) call stack, consider marking instances to better understand it&lt;/h4&gt;&lt;p&gt;Put simply, you can mark class instances so that to distinct them from other instances.&lt;/p&gt;&lt;p&gt;I had a hard time coming up with realistic example so here is not elaborated one. There is a Dog class with methods eat(Dog) and barkAt(Dog). Suppose that dog instances are dynamically created in some complicated way. You run the program and see the following call stack (in real world it will be diluted with calls on instances of other classes): &lt;a href='http://4.bp.blogspot.com/_VrU0ZHx_ziY/Sb0qdQeXspI/AAAAAAAAAME/044Ci1AMdqU/s1600-h/oo_debug_1.png' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/Sb0qdQeXspI/AAAAAAAAAME/044Ci1AMdqU/s400/oo_debug_1.png' border='0' id='BLOGGER_PHOTO_ID_5313449817493975698' alt='' style='display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 225px;' /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;From the picture we see that the Dog#eat() method is being called recursively. It doesn&amp;#8217;t necessarily mean that there is a bug in code. It may be that function is called recursively unless some condition is met. Conditions are usually based on object state so the above picture is not very helpful since it doesn&amp;#8217;t show instance on which method is called. This is where marking instances can help. You go through call stack marking &amp;#8220;this&amp;#8221; objects: &lt;a href='http://4.bp.blogspot.com/_VrU0ZHx_ziY/Sb0qdQ-fDoI/AAAAAAAAAMM/XBQng45Yt7U/s1600-h/oo_debug_2.png' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/Sb0qdQ-fDoI/AAAAAAAAAMM/XBQng45Yt7U/s400/oo_debug_2.png' border='0' id='BLOGGER_PHOTO_ID_5313449817628675714' alt='' style='display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 172px;' /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;And now, when stack shows instances of Dog, you can reason about what is going on. &lt;a href='http://2.bp.blogspot.com/_VrU0ZHx_ziY/Sb0qdmrMpLI/AAAAAAAAAMU/hcknIO9eO8Y/s1600-h/oo_debug_3.png' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/Sb0qdmrMpLI/AAAAAAAAAMU/hcknIO9eO8Y/s400/oo_debug_3.png' border='0' id='BLOGGER_PHOTO_ID_5313449823453357234' alt='' style='display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 222px;' /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h4 id='if_you_have_external_logs_files_which_you_want_to_watch_consider_watching_them_in_intellij'&gt;If you have external logs files which you want to watch, consider watching them in IntelliJ&lt;/h4&gt;&lt;p&gt;While there&amp;#8217;s nothing wrong with using external editor to watch logs (for example, &lt;a href='http://en.wikipedia.org/wiki/Less_(Unix)'&gt;less&lt;/a&gt; waiting for new input) it can be easier to watch logs in IntelliJ. IntelliJ can filter out standard and error output and do usual text-file stuff like highlighted searching (with regexps).&lt;/p&gt;&lt;p&gt;There is &amp;#8220;Logs&amp;#8221; tab in the &amp;#8220;Run/Debug Configuration&amp;#8221; window where you can setup which log files to show (for example, latest of rolling log files). The downside is that with big logs and lots of input console window in IntelliJ doesn&amp;#8217;t work very fast :(&lt;/p&gt;&lt;br /&gt;&lt;h3 id='bookmarks'&gt;BOOKMARKS&lt;/h3&gt;&lt;br /&gt;&lt;h4 id='if_there_are_several_points_in_code_to_which_you_frequently_navigate_consider_using_numbered_bookmarks'&gt;If there are several points in code to which you frequently navigate, consider using numbered bookmarks&lt;/h4&gt;&lt;p&gt;There isn&amp;#8217;t much to say about it. If you navigate to some class or method often enough, try numbered bookmark to see if it helps you to navigate faster. &lt;strong&gt;ctrl+shift+number&lt;/strong&gt; to add numbered bookmark and &lt;strong&gt;ctrl+number&lt;/strong&gt; to go to numbered bookmark.&lt;/p&gt;&lt;p&gt;Alternatively you can add classes and methods to &amp;#8220;Favorites&amp;#8221; lists (&amp;#8220;Add to favourites&amp;#8221; in context menu). See also &lt;a href='http://blogs.jetbrains.com/idea/2006/06/numbered-bookmarks/'&gt;bookmarks&lt;/a&gt; post in IntelliJ blog.&lt;/p&gt;&lt;br /&gt;&lt;h4 id='you_can_add_bookmark_with_ctrl___left_button_click_on_gutter_'&gt;You can add bookmark with ctrl + &amp;lt; left button click on gutter &amp;gt;&lt;/h4&gt;&lt;p&gt;Does the same thing as pressing F11. Can be better than F11 when you are in &amp;#8220;browsing mode&amp;#8221;.&lt;/p&gt;&lt;br /&gt;&lt;h3 id='tabs'&gt;TABS&lt;/h3&gt;&lt;br /&gt;&lt;h4 id='you_can_close_tabs_and_windows_by_clicking_with_middle_button_or_shift___left_button_click_'&gt;You can close tabs and windows by clicking with middle button or shift + &amp;lt; left button click &amp;gt;&lt;/h4&gt;&lt;p&gt;This feature was especially useful before IntelliJ 8, because there were no crosses on tabs with code. But it still works very well for closing windows. See also recent &lt;a href='http://blogs.jetbrains.com/idea/2009/03/close-mouse-shortcut/'&gt;post&lt;/a&gt; in IntelliJ blog. This feature is not IntelliJ-specific. There are many other programs (it might be better to say &amp;#8220;user interfaces&amp;#8221;) which allow user to close tabs with middle button click (eclipse, firefox, opera for example).&lt;/p&gt;&lt;br /&gt;&lt;h4 id='you_can_see_full_path_to_file_with_ctrl___left_button_click__on_its_tab'&gt;You can see full path to file with ctrl + &amp;lt; left button click &amp;gt; on its tab&lt;/h4&gt;&lt;p&gt;I don&amp;#8217;t actually use it. I imagine it could be useful if clicking on folder in the popup would open this folder in external file manager. May be you have ideas why is it there and how to use it :)&lt;/p&gt;&lt;a href='http://2.bp.blogspot.com/_VrU0ZHx_ziY/SaW63BGWQyI/AAAAAAAAALE/_gzONFmIppc/s1600-h/file_path.png' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;    &lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/SaW63BGWQyI/AAAAAAAAALE/_gzONFmIppc/s400/file_path.png' border='0' id='BLOGGER_PHOTO_ID_5306853190276629282' alt='' style='display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 189px; height: 219px;' /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h3 id='text'&gt;TEXT&lt;/h3&gt;&lt;br /&gt;&lt;h4 id='if_you_want_to_copy_several_text_chunks_from_one_file_to_another_it_may_be_easier_to_copy_them_using_clipboard_stack'&gt;If you want to copy several text chunks from one file to another, it may be easier to copy them using clipboard stack&lt;/h4&gt;&lt;p&gt;Suppose you want to copy three keys from property file and insert them into java code. Doing it &amp;#8220;normal way&amp;#8221; you would go to property file, copy one value, go to java file and paste it, then go back to property file, copy next value, go to java file and so on. There is another way to do it. You can go to property file copy all values you want (ctrl + c), then go to java file and paste them using clipboard stack (ctrl + shift + v). It&amp;#8217;s simple and can save you from switching between contexts (which you do going back and forth between files).&lt;/p&gt;&lt;p&gt;You can also use numbers to paste text from keyboard. For example, if you want to copy three values, you can copy them into clipboard, go to the target file and press &amp;#8220;ctrl + shift + v, 3, enter&amp;#8221; three times.&lt;/p&gt;&lt;p&gt;To configure clipboard stack size see &amp;#8220;Settings - Editor - Limits - Maximum number of content to keep in buffer&amp;#8221;.&lt;/p&gt;&lt;br /&gt;&lt;h4 id='if_you_want_to_compare_file_with_another_one_from_outside_of_the_project_you_can_use_compare_with_clipboard'&gt;If you want to compare file with another one from outside of the project, you can use &amp;#8220;Compare with clipboard&amp;#8221;&lt;/h4&gt;&lt;p&gt;Every now and there is a need to compare two files. It&amp;#8217;s straightforward to do if both files are within project. You select these two files and choose &amp;#8220;Compare two files&amp;#8221; in the context menu. However, it&amp;#8217;s not going to work if one of the files is not within project folder, because there is no way to select it. In this case you can copy content of external file to clipboard and use &amp;#8220;Compare with clipboard&amp;#8221; context action.&lt;/p&gt;&lt;p&gt;Sure, external diff programs can compare anything.&lt;/p&gt;&lt;br /&gt;&lt;h4 id='if_you_want_to_copy_part_of_log_without_several_left_or_right_columns_you_can_use_column_mode'&gt;If you want to copy part of log without several left (or right) columns, you can use &amp;#8220;column mode&amp;#8221;&lt;/h4&gt;&lt;p&gt;&amp;#8220;Column mode&amp;#8221; can be turned on it &amp;#8220;Edit - Column mode&amp;#8221; or with alt + shift + insert.&lt;/p&gt;&lt;a href='http://4.bp.blogspot.com/_VrU0ZHx_ziY/SaW7hEe8LtI/AAAAAAAAALM/Pn7To1XMyy4/s1600-h/column_mode_selection.png' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;    &lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/SaW7hEe8LtI/AAAAAAAAALM/Pn7To1XMyy4/s400/column_mode_selection.png' border='0' id='BLOGGER_PHOTO_ID_5306853912739589842' alt='' style='display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 136px;' /&gt;&lt;/a&gt;&lt;p&gt;Alternatively you can delete text you don&amp;#8217;t need with &amp;#8220;Replace text&amp;#8221; action using regexp mode.&lt;/p&gt;&lt;br /&gt;&lt;h4 id='you_can_copy_opened_files_path_to_clipboard_with_ctrl__shift__c'&gt;You can copy opened file&amp;#8217;s path to clipboard with ctrl + shift + c&lt;/h4&gt;&lt;p&gt;You can also do it with folders in the project view. Useful to paste path into external file manager or console. See also IntelliJ &lt;a href='http://www.jetbrains.com/idea/features/code_editor.html#Copy_path'&gt;features page&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;h4 id='if_you_want_to_use_some_constant_or_static_method_from_another_class_consider_copying_its_reference'&gt;If you want to use some constant or static method from another class, consider copying its reference&lt;/h4&gt;&lt;p&gt;This is just a way to avoid typing class name and then constant/method name. Note that you can also use it to paste {@link ..} value into javadocs. See also IntelliJ &lt;a href='http://www.jetbrains.com/idea/features/code_editor.html#Copy_reference'&gt;features page&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;h3 id='other'&gt;Other&lt;/h3&gt;&lt;br /&gt;&lt;h4 id='you_can_go_to_class_or_method_by_clicking_middle_button_on_it'&gt;You can go to class or method by clicking middle button on it&lt;/h4&gt;&lt;p&gt;Does the same thing as ctrl + &amp;lt; click &amp;gt; or pressing F4. Useful in &amp;#8220;browsing mode&amp;#8221;.&lt;/p&gt;&lt;br /&gt;&lt;h4 id='you_can_go_to_method_or_class_implementations_with_ctrl__alt___left_button_click_'&gt;You can go to method or class implementation(s) with ctrl + alt + &amp;lt; left button click &amp;gt;&lt;/h4&gt;&lt;p&gt;Useful in &amp;#8220;browsing mode&amp;#8221;. Alternatively you can open class or method hierarchy (it involves more fiddling, though).&lt;/p&gt;&lt;a href='http://1.bp.blogspot.com/_VrU0ZHx_ziY/SaW7-wWOUdI/AAAAAAAAALU/07dWbhDaARQ/s1600-h/goto_subclasses.png' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;    &lt;img src='http://1.bp.blogspot.com/_VrU0ZHx_ziY/SaW7-wWOUdI/AAAAAAAAALU/07dWbhDaARQ/s400/goto_subclasses.png' border='0' id='BLOGGER_PHOTO_ID_5306854422730396114' alt='' style='display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 54px;' /&gt;&lt;/a&gt;&lt;a href='http://2.bp.blogspot.com/_VrU0ZHx_ziY/SaW8LTz1wbI/AAAAAAAAALc/4ktrZcJx9NI/s1600-h/goto_method_implementations.png' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;    &lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/SaW8LTz1wbI/AAAAAAAAALc/4ktrZcJx9NI/s400/goto_method_implementations.png' border='0' id='BLOGGER_PHOTO_ID_5306854638408286642' alt='' style='display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 85px;' /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4 id='its_easy_to_see_where_checked_exceptions_are_thrown_by_pressing_ctrl__shift__f7_on_catchtry_keywords'&gt;It&amp;#8217;s easy to see where checked exceptions are thrown by pressing ctrl + shift + F7 on catch/try keywords&lt;/h4&gt;&lt;p&gt;It can also be handy if try-catch block catches java.lang.Exception. In this case it shows all checked exception the block catches. By the way, I still like alt + a much more than the default shortcut.&lt;/p&gt;&lt;a href='http://3.bp.blogspot.com/_VrU0ZHx_ziY/Sa2B0RL6ULI/AAAAAAAAALs/1HrUpkTJMaM/s1600-h/highlightExceptions.gif' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;    &lt;img src='http://3.bp.blogspot.com/_VrU0ZHx_ziY/Sa2B0RL6ULI/AAAAAAAAALs/1HrUpkTJMaM/s400/highlightExceptions.gif' border='0' id='BLOGGER_PHOTO_ID_5309042270706225330' alt='' style='display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 214px;' /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4 id='its_easier_to_remove_anonymous_classes_trycatch_blocks_and_etc_surrounding_some_code_with_ctrlshiftdel_rather_than_do_it_manually'&gt;It&amp;#8217;s easier to remove anonymous classes (try/catch blocks and etc.) surrounding some code with ctrl+shift+del, rather than do it manually&lt;/h4&gt;&lt;p&gt;In case you haven&amp;#8217;t seen it, take a look at &lt;a href='http://www.jetbrains.com/idea/features/code_assistance.html#Unwrap_Statement_Action'&gt;IntelliJ features (unwrap)&lt;/a&gt;. This works in IntelliJ 8 only.&lt;/p&gt;&lt;br /&gt;&lt;h4 id='try_appearance__automatically_position_mouse_cursor_on_default_button'&gt;Try &amp;#8220;Appearance - Automatically position mouse cursor on default button&amp;#8221;&lt;/h4&gt;&lt;p&gt;If you&amp;#8217;ve never used it, give it a try and may be you&amp;#8217;ll like it. Positioning mouse on default button is not specific to IntelliJ, you can as well turn on similar option in your OS.&lt;/p&gt;&lt;br /&gt;&lt;h4 id='finally_try_using_the_latest_version_of_intellij_by_participating_in_early_access_program'&gt;Finally, try using the latest version of IntelliJ by participating in &lt;a href='http://www.jetbrains.net/confluence/display/IDEADEV/EAP'&gt;Early Access Program&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Most developers don&amp;#8217;t like using &amp;#8220;nightly builds&amp;#8221; for real-world programming and this is very reasonable. We want to get our work done, not to struggle with buggy software. But there are also reasons to &lt;strong&gt;use&lt;/strong&gt; development builds. The most compelling one is that you can use latest features (it assumes that they help you with what your work on). Another reason is that not all development builds are buggy. Sure, they have more problems than a release which has been out for a year (at least it&amp;#8217;s supposed to be so), but not all problems might affect your work. It&amp;#8217;s likely that you use only a subset of functionality and there may be problems in the parts which you don&amp;#8217;t use or use rarely.&lt;/p&gt;&lt;p&gt;Regarding IntelliJ, I used EAP builds of 7 and 8 versions and from what I&amp;#8217;ve seen &lt;a href='http://www.jetbrains.net/confluence/display/IDEADEV/EAP'&gt;EAP&lt;/a&gt; builds are good enough to be used for day-to-day work. So wait until April or so for IntelliJ 9 and give it a try ;)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-2827498988025141867?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=agNDnxzSBx0:_oBBGgKI4-0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=agNDnxzSBx0:_oBBGgKI4-0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=agNDnxzSBx0:_oBBGgKI4-0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=agNDnxzSBx0:_oBBGgKI4-0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=agNDnxzSBx0:_oBBGgKI4-0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=agNDnxzSBx0:_oBBGgKI4-0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=agNDnxzSBx0:_oBBGgKI4-0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=agNDnxzSBx0:_oBBGgKI4-0:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/agNDnxzSBx0" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-18T13:14:43.661-08:00</app:edited><media:thumbnail url="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SaWyiHj0qKI/AAAAAAAAAKs/Xq5C0jHdMRY/s72-c/eval_in_debug.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2009/03/misc-intellij-tips.html</feedburner:origLink></item><item><title>Yak scratching</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/7m6VNA4WWC8/yak-scratching.html</link><category>yak</category><category>software development</category><category>methodology</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Fri, 27 Feb 2009 15:20:37 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-7722117630597684597</guid><description>&lt;p&gt;Recently when reading &lt;a href='http://blogs.thoughtworks.com/'&gt;Thoughtworks blogs&lt;/a&gt; I coined the &lt;a href='http://en.wiktionary.org/wiki/yak_shaving'&gt;&amp;#8220;yak-shaving&amp;#8221;&lt;/a&gt; term. It means &amp;#8220;any seemingly pointless activity which is actually necessary to solve a problem which solves a problem which, several levels of recursion later, solves the real problem you&amp;#8217;re working on&amp;#8221;. There is also an &lt;a href='http://sethgodin.typepad.com/seths_blog/2005/03/dont_shave_that.html'&gt;interpretation&lt;/a&gt; such as &amp;#8220;doing it well now is much better than doing it perfectly later&amp;#8221;, but I like the first one better.&lt;/p&gt;&lt;p&gt;As one can expect from working in a big company on &amp;#8220;legacy system&amp;#8221; it allows you to experience a lot of yak-shaving activities. For example, you want to catch breakpoint to understand a piece of code or make sure you change actually works (ask me why you cannot.. don&amp;#8217;t write unit test). To catch breakpoint you would need database server on other continent, several feeds and services to be up (they can occasionally be down) and probably a remote desktop connection to market emulator which is shared by a whole bunch of people.&lt;/p&gt;&lt;a href='http://4.bp.blogspot.com/_VrU0ZHx_ziY/SahtJ_x2EII/AAAAAAAAALk/g2EqB4k2X3w/s1600-h/yak.jpg' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/SahtJ_x2EII/AAAAAAAAALk/g2EqB4k2X3w/s400/yak.jpg' border='0' id='BLOGGER_PHOTO_ID_5307612179362877570' alt='yak' style='float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 239px; height: 240px;' /&gt;&lt;/a&gt;&lt;p&gt;After reading about yak-shaving I retold the story to several co-workers. Some of them didn&amp;#8217;t get it, some (those who know the pain of yak-shaving) enjoyed it, but best of all I liked one response. I told a guy the &lt;a href='http://sethgodin.typepad.com/seths_blog/2005/03/dont_shave_that.html'&gt;yak-story&lt;/a&gt;, he spent about half-an-hour trying to get a breakpoint according to the above &amp;#8220;methodology&amp;#8221; and then exclaimed &amp;#8221;I&amp;#8217;m &lt;strong&gt;scratching&lt;/strong&gt; the yak&amp;#8221;. This, I believe, is more precise description of what we sometimes do. You&amp;#8217;re not just shaving it, but &lt;strong&gt;scratching&lt;/strong&gt;. You may know with some degree of certainty how to get to the actual problem, but obstacles you face are so uncertain, unrepeatable and numerous, that despite all efforts you get nowhere and the only thing you left with is misery and despair. Indeed &amp;#8220;shaving&amp;#8221; sounds to optimistic in this case. &amp;#8220;Shaving&amp;#8221; assumes you&amp;#8217;re making progress. But when you stuck with some totally unrelated problem for hours and then you get another one and then another, &amp;#8220;scratching the yak&amp;#8221; seems much more appropriate term.&lt;/p&gt;&lt;p&gt;Does it have to be this way? Why do we do yak-scratching? (I won&amp;#8217;t go into &lt;a href='http://en.wikipedia.org/wiki/5_Whys'&gt;five why&amp;#8217;s&lt;/a&gt;.) What can we do about it? May be it&amp;#8217;s our incompetence and lack of knowledge? May be it&amp;#8217;s the way big systems are developed? Or may be it&amp;#8217;s yaks&amp;#8217; conspiracy? From technical point of view we could separate system into modules with clear contracts. Develop modules separately. Create &lt;a href='http://xunitpatterns.com/Fake%20Object.html'&gt;fakes&lt;/a&gt; for external systems and write &lt;a href='http://xunitpatterns.com/Goals%20of%20Test%20Automation.html'&gt;automated tests&lt;/a&gt;. Sounds good but it requires &lt;strong&gt;political&lt;/strong&gt; will. You have to convince management it will pay off for business. You have to convince people who work on project it won&amp;#8217;t change one yak to another. Not to mention you have to be sure you&amp;#8217;re right. (I realize it can be self-deception and blaming others is not a solution anyway.)&lt;/p&gt;&lt;p&gt;Not all technical problems are really technical. Beware of yaks.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-7722117630597684597?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=7m6VNA4WWC8:crfGn_OgYag:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=7m6VNA4WWC8:crfGn_OgYag:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=7m6VNA4WWC8:crfGn_OgYag:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=7m6VNA4WWC8:crfGn_OgYag:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=7m6VNA4WWC8:crfGn_OgYag:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=7m6VNA4WWC8:crfGn_OgYag:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?i=7m6VNA4WWC8:crfGn_OgYag:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/SvAh?a=7m6VNA4WWC8:crfGn_OgYag:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/SvAh?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/7m6VNA4WWC8" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-27T15:20:37.111-08:00</app:edited><media:thumbnail url="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SahtJ_x2EII/AAAAAAAAALk/g2EqB4k2X3w/s72-c/yak.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2009/02/yak-scratching.html</feedburner:origLink></item><item><title>Debugging managers</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/pXXX9S2evGc/debugging-managers.html</link><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Thu, 19 Feb 2009 02:38:45 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-4003670311618318255</guid><description>&lt;p&gt;The other day I was debugging the application I work on. At some point looking at the debug window in a &amp;#8220;context free&amp;#8221; way I realized that there is a whole lot managers in it and what I&amp;#8217;m doing is basically debugging managers of managers.&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SZ0ysWbnaYI/AAAAAAAAAKk/NcY0f5K0px4/s1600-h/debugging_managers.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 164px;" src="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SZ0ysWbnaYI/AAAAAAAAAKk/NcY0f5K0px4/s400/debugging_managers.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5304451673629354370" /&gt;&lt;/a&gt;
&lt;/p&gt;&lt;p&gt;It&amp;#8217;s no that I think it&amp;#8217;s a bad design or these classes are badly named (they could&amp;#8217;ve been better, though). And it&amp;#8217;s not that I think this structure is too complicated, after all there are only three levels of managers in the picture (actually more).&lt;/p&gt;&lt;p&gt;What drew my attention was the idea that choice of class names is influenced by organization, its structure and its language. The place I work at use model like: coding monkey &amp;#8211;&amp;gt; manager &amp;#8211;&amp;gt; superhero manager. Where the last two stages are obviously bound to be attractive. Now imagine how many times you can read the word &amp;#8220;manager&amp;#8221; in code (fields, parameter, local variables) given the huge number of manager classes. Admittedly it&amp;#8217;s not very useful idea, since I can hardly imagine how one could benefit from it.&lt;/p&gt;&lt;p&gt;As the &lt;a href='http://en.wikipedia.org/wiki/Conway&amp;apos;s_Law'&gt;Conway&amp;#8217;s Law&lt;/a&gt; (which sound like &amp;#8220;any piece of software reflects the organizational structure that produced it&amp;#8221;) the idea of code being influenced by corporate language boils down to the fact that it&amp;#8217;s people who produce software and they inevitably leave traces.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-4003670311618318255?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=DIQQEsDi"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=SPmodqMa"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=SPmodqMa" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=xucJAmsw"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=xucJAmsw" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=hwjC3AQc"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=hwjC3AQc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=HUW6nJuz"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=129" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/pXXX9S2evGc" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-19T02:38:45.443-08:00</app:edited><media:thumbnail url="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SZ0ysWbnaYI/AAAAAAAAAKk/NcY0f5K0px4/s72-c/debugging_managers.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2009/02/debugging-managers.html</feedburner:origLink></item><item><title>IntelliJ IDEA 2.6</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/jqG0Y2zOrF0/intellij-idea-26.html</link><category>intellij</category><category>software history</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Sun, 08 Feb 2009 01:45:46 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-5754831335114627960</guid><description>&lt;p&gt;It&amp;#8217;s always interesting to see what things were like in the past. It&amp;#8217;s even more interesting to see things that are not easily accessible. I can always start vi and pretend I&amp;#8217;m in 70s but since it&amp;#8217;s so easy to do and because vi (or vim) installed almost on any *nix box it&amp;#8217;s not fun. Therefore, I tried old versions of IntelliJ.&lt;/p&gt;&lt;p&gt;I got into java somewhere about 2004. As you can guess in 2004 IntelliJ IDEA 4 was the latest version (you can guess because IntelliJ versions correspond to the current year, so in 2011 there will be IntelliJ 11) and I&amp;#8217;ve never used any version prior to 4. Recently I got hold of IntelliJ version 2 and 3 (you can download version 3 &lt;a href='http://www.jetbrains.net/devnet/docs/DOC-71'&gt;here&lt;/a&gt;). Summarizing my impression in three words &amp;#8220;they are fast&amp;#8221;. Here are some screenshots of IntelliJ 2 to get a feel of what it was like.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_VrU0ZHx_ziY/SY6JZYm5FlI/AAAAAAAAAHc/91ZwwqioEec/s1600-h/splash.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 398px; height: 299px;" src="http://3.bp.blogspot.com/_VrU0ZHx_ziY/SY6JZYm5FlI/AAAAAAAAAHc/91ZwwqioEec/s400/splash.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300324880656963154" /&gt;&lt;/a&gt;
It's not cracked ;) Just don't want to disclose the owner.&lt;br/&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_VrU0ZHx_ziY/SY6Kd2KqiBI/AAAAAAAAAHk/rzwFLgKPrG0/s1600-h/class-structure.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 233px;" src="http://2.bp.blogspot.com/_VrU0ZHx_ziY/SY6Kd2KqiBI/AAAAAAAAAHk/rzwFLgKPrG0/s400/class-structure.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300326056822736914" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SY6Kd4jU4OI/AAAAAAAAAHs/71uHtUVTFoI/s1600-h/debugging.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 235px;" src="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SY6Kd4jU4OI/AAAAAAAAAHs/71uHtUVTFoI/s400/debugging.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300326057463046370" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_VrU0ZHx_ziY/SY6KeLaNSGI/AAAAAAAAAH0/z2udfcaztL8/s1600-h/menu-code.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 233px;" src="http://2.bp.blogspot.com/_VrU0ZHx_ziY/SY6KeLaNSGI/AAAAAAAAAH0/z2udfcaztL8/s400/menu-code.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300326062525073506" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_VrU0ZHx_ziY/SY6KeLV84-I/AAAAAAAAAH8/pUmI6e5XTrY/s1600-h/menu-goto.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 233px;" src="http://1.bp.blogspot.com/_VrU0ZHx_ziY/SY6KeLV84-I/AAAAAAAAAH8/pUmI6e5XTrY/s400/menu-goto.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300326062507221986" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_VrU0ZHx_ziY/SY6KeAB16uI/AAAAAAAAAIE/26GCu7a_EZ0/s1600-h/menu-refactoring.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 235px;" src="http://2.bp.blogspot.com/_VrU0ZHx_ziY/SY6KeAB16uI/AAAAAAAAAIE/26GCu7a_EZ0/s400/menu-refactoring.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300326059470088930" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_VrU0ZHx_ziY/SY6LAxvtSsI/AAAAAAAAAIM/_5lVchqfbaw/s1600-h/autoimport.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 233px;" src="http://1.bp.blogspot.com/_VrU0ZHx_ziY/SY6LAxvtSsI/AAAAAAAAAIM/_5lVchqfbaw/s400/autoimport.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300326656931351234" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SY6LAyOs4QI/AAAAAAAAAIU/hpq4V-AhQiE/s1600-h/method-autocomplete.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 233px;" src="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SY6LAyOs4QI/AAAAAAAAAIU/hpq4V-AhQiE/s400/method-autocomplete.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300326657061347586" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_VrU0ZHx_ziY/SY6L3ryUR3I/AAAAAAAAAJs/ip9J8OiIk0c/s1600-h/text-highlight.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 233px;" src="http://3.bp.blogspot.com/_VrU0ZHx_ziY/SY6L3ryUR3I/AAAAAAAAAJs/ip9J8OiIk0c/s400/text-highlight.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300327600224487282" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_VrU0ZHx_ziY/SY6LV_k57tI/AAAAAAAAAI0/PWHWSMmshRE/s1600-h/class-outline.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 400px;" src="http://1.bp.blogspot.com/_VrU0ZHx_ziY/SY6LV_k57tI/AAAAAAAAAI0/PWHWSMmshRE/s400/class-outline.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300327021421391570" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_VrU0ZHx_ziY/SY6LBEZaaeI/AAAAAAAAAIs/rlf5YoAkTgw/s1600-h/popup-new.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 64px; height: 108px;" src="http://3.bp.blogspot.com/_VrU0ZHx_ziY/SY6LBEZaaeI/AAAAAAAAAIs/rlf5YoAkTgw/s400/popup-new.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300326661938112994" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SY6LBGT_1VI/AAAAAAAAAIk/Ai_cu6UNuZw/s1600-h/popup-surround-with.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 119px; height: 241px;" src="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SY6LBGT_1VI/AAAAAAAAAIk/Ai_cu6UNuZw/s400/popup-surround-with.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300326662452270418" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_VrU0ZHx_ziY/SY6LBABQgbI/AAAAAAAAAIc/wzJD_kTTEBo/s1600-h/popup-generate.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 108px; height: 108px;" src="http://1.bp.blogspot.com/_VrU0ZHx_ziY/SY6LBABQgbI/AAAAAAAAAIc/wzJD_kTTEBo/s400/popup-generate.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300326660763058610" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_VrU0ZHx_ziY/SY6L3a8BbSI/AAAAAAAAAJk/z6NU4FrRPMQ/s1600-h/popup-live-template.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 147px;" src="http://3.bp.blogspot.com/_VrU0ZHx_ziY/SY6L3a8BbSI/AAAAAAAAAJk/z6NU4FrRPMQ/s400/popup-live-template.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300327595701792034" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SY6L3Q0et5I/AAAAAAAAAJc/Dl8XrJff8QA/s1600-h/breakpoint-options.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 279px;" src="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SY6L3Q0et5I/AAAAAAAAAJc/Dl8XrJff8QA/s400/breakpoint-options.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300327592985802642" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SY6LWH3T6rI/AAAAAAAAAJU/dBonkWoedK0/s1600-h/run-configuration.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 333px;" src="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SY6LWH3T6rI/AAAAAAAAAJU/dBonkWoedK0/s400/run-configuration.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300327023646075570" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_VrU0ZHx_ziY/SY6LWPyYBVI/AAAAAAAAAJM/qHmVi7s_Tvw/s1600-h/options-filetypes.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 297px;" src="http://1.bp.blogspot.com/_VrU0ZHx_ziY/SY6LWPyYBVI/AAAAAAAAAJM/qHmVi7s_Tvw/s400/options-filetypes.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300327025772856658" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_VrU0ZHx_ziY/SY6LWHsc0bI/AAAAAAAAAJE/OsA1AQQ6Oo8/s1600-h/optinos-keymap.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 297px;" src="http://1.bp.blogspot.com/_VrU0ZHx_ziY/SY6LWHsc0bI/AAAAAAAAAJE/OsA1AQQ6Oo8/s400/optinos-keymap.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300327023600521650" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SY6LV4mI4FI/AAAAAAAAAI8/YgSyPwNFKIQ/s1600-h/properties-compiler.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 309px;" src="http://4.bp.blogspot.com/_VrU0ZHx_ziY/SY6LV4mI4FI/AAAAAAAAAI8/YgSyPwNFKIQ/s400/properties-compiler.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300327019547517010" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-5754831335114627960?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=qJdwwvBH"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=jVas5Lpe"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=jVas5Lpe" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=0V2q38eu"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=0V2q38eu" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=zcCvYyxg"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=zcCvYyxg" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=ibVnWfDW"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=129" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/jqG0Y2zOrF0" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-08T01:45:46.180-08:00</app:edited><media:thumbnail url="http://3.bp.blogspot.com/_VrU0ZHx_ziY/SY6JZYm5FlI/AAAAAAAAAHc/91ZwwqioEec/s72-c/splash.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2009/02/intellij-idea-26.html</feedburner:origLink></item><item><title>Estimation</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/oRSNgWVdqII/estimation.html</link><category>java</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Mon, 09 Feb 2009 13:37:15 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-3750645964274745863</guid><description>&lt;p&gt;Quick! How long does it take to execute about 200 lines of java code (no I/O) on your machine? Why does it take 70 milliseconds?&lt;/p&gt;&lt;p&gt;This is the kind of problem I faced yesterday (although, I didn&amp;#8217;t actually measure how many line of java code there was). So I add several breakpoints logging current time to console. In IntelliJ you can click on gutter with Shift pressed (doesn&amp;#8217;t work in KDE4 at the time of writing) and get window like this one.&lt;/p&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_VrU0ZHx_ziY/SYqEKEstaaI/AAAAAAAAAHU/Szc-wIZREI8/s1600-h/debug.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 223px;" src="http://2.bp.blogspot.com/_VrU0ZHx_ziY/SYqEKEstaaI/AAAAAAAAAHU/Szc-wIZREI8/s400/debug.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5299193220149635490" /&gt;&lt;/a&gt;
&lt;p&gt;After running code with breakpoints output shows that there is from 15 to 30 milliseconds delay between each of breakpoints, which add up to some 70ms. Is it all? I thought so, but it&amp;#8217;s not. After suggestion from a colleague to try &amp;#8220;profiling&amp;#8221; without writing to console straightaway, I added code like this one (not real code):&lt;/p&gt;&lt;pre style='color:rgb(0,0,0);font-weight:normal;font-style:normal;border:thin solid;padding:5px;font-family:monospace;'&gt;
    &lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;public&lt;/span&gt; &lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;static&lt;/span&gt; &lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;final&lt;/span&gt; &lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;long&lt;/span&gt; &lt;span style='color:rgb(102,14,122);font-weight:bold;font-style:italic;'&gt;TIMES&lt;/span&gt;[] = &lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;new&lt;/span&gt; &lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;long&lt;/span&gt;[&lt;span style='color:rgb(0,0,255);font-weight:normal;font-style:normal;'&gt;20&lt;/span&gt;];

    &lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;public&lt;/span&gt; &lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;static&lt;/span&gt; &lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;void&lt;/span&gt; takeTimestamp(&lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;int&lt;/span&gt; i) {
        &lt;span style='color:rgb(102,14,122);font-weight:bold;font-style:italic;'&gt;TIMES&lt;/span&gt;[i] = System.&lt;span style='color:rgb(0,0,0);font-weight:normal;font-style:italic;'&gt;currentTimeMillis&lt;/span&gt;();
    }

    &lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;public&lt;/span&gt; &lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;static&lt;/span&gt; &lt;span style='color:rgb(0,0,128);font-weight:bold;font-style:normal;'&gt;void&lt;/span&gt; main(String[] args) {
        &lt;span style='color:rgb(0,0,0);font-weight:normal;font-style:italic;'&gt;takeTimestamp&lt;/span&gt;(&lt;span style='color:rgb(0,0,255);font-weight:normal;font-style:normal;'&gt;0&lt;/span&gt;);
        &lt;span style='color:rgb(128,128,128);font-weight:normal;font-style:italic;'&gt;// ... some code&lt;/span&gt;
        &lt;span style='color:rgb(0,0,0);font-weight:normal;font-style:italic;'&gt;takeTimestamp&lt;/span&gt;(&lt;span style='color:rgb(0,0,255);font-weight:normal;font-style:normal;'&gt;1&lt;/span&gt;);

&lt;/pre&gt;&lt;p&gt;I ran it without debugger attached and see that output is a bit strange because &lt;em&gt;all timestamps are the same&lt;/em&gt;. I do make stupid mistakes sometimes, but with code like the above it seems very unlikely. I change timestamps to &lt;em&gt;nanoseconds&lt;/em&gt; and see quite surprising result. There are no mistakes, it's just that code I&amp;#8217;m &amp;#8220;profiling&amp;#8221; executes in less than &lt;em&gt;1&lt;/em&gt; millisecond.&lt;/p&gt;&lt;p&gt;Lessons learned:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;don&amp;#8217;t &amp;#8220;profile&amp;#8221; with debugger attached.&lt;/li&gt;&lt;li&gt;&amp;#8220;for interval timing, always use System.nanoTime in preference to System.currentTimeMillis&amp;#8221; (see &lt;a href='http://www.amazon.com/gp/product/0321356683?ie=UTF8&amp;amp;tag=tepe0d-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0321356683'&gt;EJ 2nd edition&lt;/a&gt;). I could&amp;#8217;ve saved some time if I followed this advice. I knew I should do it, but didn&amp;#8217;t remember why and, seeing that several other developers use currentTimeMillis() in preference of nanoTime(), decided to use it too. Really bad idea. The reason is that it&amp;#8217;s platform specific and on XP machine it may have &amp;#8220;a granularity of 15 ms&amp;#8221; (see &lt;a href='http://www.techper.net/2008/08/10/systemcurrenttimemillis-systemnanotime-and-their-resolution/'&gt;this post&lt;/a&gt;).&lt;/li&gt;&lt;li&gt;most importantly you should be able to &amp;#8220;Estimate to Avoid Surprises&amp;#8221; (see &lt;a href='http://www.pragprog.com/the-pragmatic-programmer/extracts/tips'&gt;The Pragmatic Programmer&lt;/a&gt; Tip 18).&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;Update: I wasn't benchmarking but rather measuring how long it takes for specific code path to be executed in live environment under certain conditions. Should you want to do benchmarking you probably should look at something like framework &lt;a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html"&gt;from this article&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-3750645964274745863?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=DX2pOuLo"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=X1P1l9rI"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=X1P1l9rI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=OX7bSu6L"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=OX7bSu6L" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=1Xuus0TI"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=1Xuus0TI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=0Yshw3KI"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=129" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/oRSNgWVdqII" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-09T13:37:15.782-08:00</app:edited><media:thumbnail url="http://2.bp.blogspot.com/_VrU0ZHx_ziY/SYqEKEstaaI/AAAAAAAAAHU/Szc-wIZREI8/s72-c/debug.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2009/02/estimation.html</feedburner:origLink></item><item><title>Software history tidbits from Joel</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/ssJjnQKfQzQ/software-history-tidbits-from-joel.html</link><category>joel on software</category><category>software history</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Wed, 04 Feb 2009 13:26:38 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-7275840758135511846</guid><description>&lt;p&gt;I&amp;#8217;ve been reading old articles by Joel Spolsky lately. Starting with &lt;a href='java_post'&gt;post&lt;/a&gt; mocking java installation dialog, I went to &lt;a href='people_dont_read'&gt;&amp;#8220;People don&amp;#8217;t like to read&amp;#8221; link&lt;/a&gt; and was absorbed by adjacent articles. While enjoying old stories about UI design I found that there are quite a lot of things I don&amp;#8217;t know about the past of software industry. Here are some things I read on Joel&amp;#8217;s site and googled afterwards (they might be not surprising in the least to you, though):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;in the 80&amp;#8217;s and early 90&amp;#8217;s there was &amp;#8220;almost complete monopoly&amp;#8221; by Lotus 123 on the spreadsheet market and Microsoft overtook it by making Excel &lt;em&gt;compatible&lt;/em&gt; with Lotus.&lt;/li&gt;&lt;li&gt;&amp;#8220;when Microsoft Excel 3.0 came out in 1990, it was the first application to sport a &lt;em&gt;new feature&lt;/em&gt; called a toolbar&amp;#8221;&lt;/li&gt;&lt;li&gt;there was a &lt;em&gt;complete rewrite&lt;/em&gt; of Netscape Navigator which lasted for 3 years and gave IE an opportunity to take over the browser market&lt;/li&gt;&lt;li&gt;IE was default browser on Mac for 5 years (I believe I&amp;#8217;ve heard about it but since I never owned a Mac I didn&amp;#8217;t really care)&lt;/li&gt;&lt;li&gt;Opera is much older than I though with the first release in 1994 (this is from &lt;a href='http://upload.wikimedia.org/wikipedia/commons/7/74/Timeline_of_web_browsers.svg'&gt;browsers timeline&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I wonder if there is some book about software history over the last 15 years or so.&lt;/p&gt;&lt;p&gt;Update:&lt;/p&gt;&lt;p&gt;There was a good illustration of why I don&amp;#8217;t read Joel often in his &lt;a href='http://blog.stackoverflow.com/2009/01/podcast-38/'&gt;podcast #38&lt;/a&gt; and following &lt;a href='http://blog.objectmentor.com/articles/2009/01/31/quality-doesnt-matter-that-much-jeff-and-joel'&gt;blog post by Robert Martin&lt;/a&gt; (with lots of interesting comments). In my view Joel and Jeff make a good point that software development techniques are just tools to provide &amp;#8220;business value&amp;#8221;. On the other hand, they obviously didn&amp;#8217;t try to understand SOLID principles before criticising them. Not to mention that regarding usefulness of TDD I&amp;#8217;m totally on the side of Robert Martin :) Looking forward to listening stack overflow with Robert Martin.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-7275840758135511846?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=JZO9RQL1"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=dK3OkxRD"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=dK3OkxRD" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=Y73oYP4A"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=Y73oYP4A" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=YVuuQ4u9"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=YVuuQ4u9" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=0GkjLxsm"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=129" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/ssJjnQKfQzQ" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-04T13:26:38.630-08:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2009/01/software-history-tidbits-from-joel.html</feedburner:origLink></item><item><title>I plugged in to IntelliJ :)</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/_-SXVqcRWnY/i-plugged-in-to-intellij.html</link><category>java</category><category>intellij</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Mon, 29 Dec 2008 14:26:01 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-6717493568953567265</guid><description>&lt;p&gt;This year I found some time to take part in &lt;a href='http://plugins.intellij.net/contest'&gt;IntelliJ plugin contest&lt;/a&gt;. I started writing code only two weeks before the end of the contest, though. So the most reasonable prize I could hope for from the very beginning was &lt;a href='http://plugins.intellij.net/contest/tshirt.html'&gt;&amp;#8220;I plugged in to IntelliJ&amp;#8221; t-shirt&lt;/a&gt; which all the participants get. The reason I chose to write html export is that I didn&amp;#8217;t like in the default IDEA export. It lacks annotations and static fields highlighting and have problems with multiline java-docs. Javascript-based highlighters that I tried weren&amp;#8217;t very good at highlighting static fields and methods either. Therefore, I rolled up &lt;a href='http://plugins.intellij.net/plugin/?id=3828'&gt;plugin for html export&lt;/a&gt;. (There is also &lt;a href='http://plugins.intellij.net/plugin/?id=190'&gt;Copy as HTML plugin&lt;/a&gt; which does mostly the same thing. It might be a good idea to update it to IntelliJ 8 API but after looking at the code I though better off it. Sorry. I&amp;#8217;m a bit tired of making sense of and changing code I didn&amp;#8217;t write at work.)&lt;/p&gt;&lt;p&gt;All in all I really enjoyed the process of plugin-writing. I don&amp;#8217;t think of it as being &amp;#8220;finished&amp;#8221; and plan to add more features. Here are some things I learned while doing it.&lt;/p&gt;&lt;h2 id='tdd_doesnt_replace_thinking_beforehand'&gt;TDD doesn&amp;#8217;t replace thinking beforehand&lt;/h2&gt;&lt;p&gt;I admit I&amp;#8217;ve been and probably still is over-enthusiastic about unit testing and TDD in particular. In my understanding the idea behind doing TDD and not thinking through the whole problem is that you cannot possibly know all the obstacles you&amp;#8217;re going to encounter and, therefore, it might be more practical to write some code and learn from this experience. Sometimes this approach works very well, sometimes doesn&amp;#8217;t. The only rule that holds true most of the time is that there are no silver bullets and and it&amp;#8217;s a judgement call to decide whether some technique can be applied or not (well.. unless you do the same thing all the time). As I found it might be more effective to write some code (I don&amp;#8217;t say write &amp;#8220;spike code&amp;#8221;) and run system in live environment to get broader view of problem, rather than start with unit tests right away.&lt;/p&gt;&lt;h2 id='there_is_no_right_scope_for_unit_tests'&gt;There is no &amp;#8220;right&amp;#8221; scope for unit tests&lt;/h2&gt;&lt;p&gt;It was after reading &lt;a href='http://xunitpatterns.com/'&gt;xUnit Patterns&lt;/a&gt; and &lt;a href='http://www.amazon.com/Working-Effectively-Legacy-Robert-Martin/dp/0131177052'&gt;Working Effectively with Legacy Code&lt;/a&gt; books that I became keen on writing small-scoped tests which wouldn&amp;#8217;t interact with other classes or even worse with filesystem of database. These are actually the qualities that make them &amp;#8220;unit&amp;#8221; tests. It seems to me now &lt;em&gt;unit&lt;/em&gt; tests are not the best choice in every case (I mean even when it&amp;#8217;s possible to write meaningful unit tests). Sometimes it&amp;#8217;s better to write larger-scoped system-level tests. The reason is that unit tests are coupled to interfaces of classes they are written for and, should you want to make big changes in implementation (throwing away or changing a lot of classes along the way, for example), unit tests will be of little help. &lt;a href='http://www.threeriversinstitute.org/WhereToTest.html'&gt;Here is&lt;/a&gt; a pretty good article by Kent Beck on this topic.&lt;/p&gt;&lt;h2 id='find_and_grep_are_faster_than_ide_search'&gt;&amp;#8220;find&amp;#8221; and &amp;#8220;grep&amp;#8221; are faster than IDE search&lt;/h2&gt;&lt;p&gt;I&amp;#8217;ve been aware for quite a while that I could use something like&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;find . -name * | xargs grep &amp;#8220;some text&amp;#8221;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I used it occasionally on remote machines but I&amp;#8217;ve never seriously thought of using it on desktop. After all why would I want to with modern IDEs and file managers? The answer is because &amp;#8220;find&amp;#8221; with &amp;#8220;grep&amp;#8221; is way faster. I don&amp;#8217;t have exact numbers but on projects with large code base textual search in IntelliJ, Eclipse or &lt;a href='http://www.krusader.org/'&gt;Krusader&lt;/a&gt; may take ten seconds or more. On the same code bases grep does the same thing in just seconds&lt;/p&gt;&lt;h2 id='checklists_are_great'&gt;Checklists are great&lt;/h2&gt;&lt;p&gt;They really help to make sure you don&amp;#8217;t forget anything. Although the idea of using checklists is not new, I&amp;#8217;ve never seen a developer sitting next to me who would use a checklist. I wouldn&amp;#8217;t use it either if not for &lt;a href='http://stepin.name'&gt;Igor Stepin&lt;/a&gt; who mentioned checklists in some discussion.&lt;/p&gt;&lt;p&gt;To make it more concrete here is a snippet from htmlexport &amp;#8220;release checklist&amp;#8221;.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;- fix all todos&lt;/p&gt;&lt;p&gt;- review code (optional)&lt;/p&gt;&lt;p&gt;- run DSM&lt;/p&gt;&lt;p&gt;- run Intellij code review&lt;/p&gt;&lt;p&gt;- make sure all tests pass&lt;/p&gt;&lt;p&gt;- test plugin manually with java, xml&lt;/p&gt;&lt;p&gt;- update plugin xml&lt;/p&gt;&lt;p&gt;- run plugin build from IntelliJ&lt;/p&gt;&lt;p&gt;&amp;#8230;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;As an afterthought, refactoring descriptions are in fact checklists, but I admit I use built-in IDE refactorings or refactor without any guide.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-6717493568953567265?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=TBpNnUgL"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=NaqcVSz7"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=NaqcVSz7" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=wnDK4ZJ6"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=wnDK4ZJ6" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=lmjUPfwI"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=lmjUPfwI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=GKGcMtoH"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=129" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/_-SXVqcRWnY" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-29T14:26:01.320-08:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2008/12/i-plugged-in-to-intellij.html</feedburner:origLink></item><item><title>Gem 'ruby-debug-ide' not found in IntelliJ under Kubuntu</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/ZHhwRGr9x3A/gem-ruby-debug-ide-not-found-in.html</link><category>ruby</category><category>rubymine</category><category>intellij</category><category>kubuntu</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Sun, 09 Nov 2008 07:29:19 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-8004157992790892744</guid><description>&lt;p&gt;A while ago when IntelliJ got the ability to debug ruby scripts I tried to set it up under Kubuntu what turned out to be not very straightforward. Firstly, there must be ruby-debug-ide gem installed. It seems to be not a big deal? Right, it&amp;#8217;s not a big deal to type&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;gem install ruby-debug-ide&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;But with default Kubuntu installation (8.4 at that time) it would fail when building some system dependent sources. Thanks to &lt;a href='http://www.linkedin.com/in/igorstepin'&gt;Igor Stepin&lt;/a&gt;, who suggested installing build-essentials package, I got around this problem.&lt;/p&gt;&lt;p&gt;The second problem was that even though ruby-debug-ide was installed IntelliJ kept saying it cannot find it. The solution is also not very tricky: you should change &amp;#8220;Gem bin directory&amp;#8221; in JDK setting from &amp;#8220;/usr/bin&amp;#8221; (which is default) to &amp;#8220;/var/lib/gems/1.8/bin&amp;#8221;.&lt;/p&gt;&lt;p&gt;The same applies to debugging in &lt;a href='http://www.jetbrains.com/ruby/'&gt;RubyMine&lt;/a&gt;. I didn&amp;#8217;t manage to find SDK configuration dialog in 435 build and, therefore, fixed configuration through xml configs by copying part of IntelliJ&amp;#8217;s jdk.table.xml to ~/.RubyMine10/config/options/jdk.table.xml (text configurations rule!).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-8004157992790892744?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=8SlbDBDq"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=qpKW4erp"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=qpKW4erp" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=O4jTzg5h"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=O4jTzg5h" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=FVDulrZh"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=FVDulrZh" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=9zTff5cj"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=129" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/ZHhwRGr9x3A" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-09T07:29:19.463-08:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2008/11/gem-ruby-debug-ide-not-found-in.html</feedburner:origLink></item><item><title>Bluetooth in kubuntu 8.10 by hands</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/ehe8XAqhD3U/bluetooth-in-kubuntu-810-by-hands.html</link><category>bluetooth</category><category>kde4</category><category>kubuntu</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Sat, 08 Nov 2008 05:44:40 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-4328756818839831378</guid><description>&lt;p&gt;I recently updated my desktop Kubuntu to &lt;a href='http://www.kubuntu.org/news/8.10-release'&gt;8.10&lt;/a&gt; which among other things doesn&amp;#8217;t have KDE 3.5 anymore but only KDE 4.1. I really liked KDE 3 which all things considered is the best window manager I&amp;#8217;ve ever used (three years ago I wouldn&amp;#8217;t believe I&amp;#8217;d say it but here I am) and, therefore, transition to KDE 4 is pretty much painful for me. One of the problems I encountered was the lack of bluetooth support in KDE 4 which IMHO is something inconceivable for a major distribution like Ubuntu.&lt;/p&gt;&lt;p&gt;Anyways, the only thing I use bluetooth for is to download and remove photographs from cell phone (Sony Ericsson 500i). My first attempt was to install bluez-gnome and use bluetooth-applet as it is suggested in &lt;a href='https://bugs.launchpad.net/ubuntu/+source/kdebase-workspace/+bug/280997'&gt;this bug report&lt;/a&gt;. Unfortunately, for some reason bluetooth-applet didn&amp;#8217;t work. I could see cell phone but &amp;#8220;Browse files on device&amp;#8221; menu item was disabled no matter what I did. Being desperate after several attempts, I even tried to setup bluetooth in Vista (which was shipped with my laptop). To my surprise it was not easy either because Vista wanted some drivers which it couldn&amp;#8217;t find on Internet. And all this after KDE 3 where it took me literally 1 minute to setup bluetooth so that to edit cell phone filesystem.&lt;/p&gt;&lt;p&gt;Of course, no bluetooth in KDE 4 doesn&amp;#8217;t mean you cannot use it at all. So after some googling I found out that there is obextftp command line tool which can be used as shown &lt;a href='http://www.thinkwiki.org/wiki/How_to_setup_Bluetooth#File_Transfer'&gt;here&lt;/a&gt; or &lt;a href='http://www.klabs.be/~fpiat/linux/debian/SonyEricsson_M600i_on_Linux_Debian_Etch.html'&gt;here&lt;/a&gt;. After a little while I ended up with small script which finds directory with photos and downloads photos to the current directory:&lt;/p&gt;&lt;pre&gt;
&lt;b&gt;#!/usr/bin/ruby&lt;/b&gt;

&lt;span style='color: #bb1188'&gt;&lt;b&gt;PHONE_MAC&lt;/b&gt;&lt;/span&gt; &lt;span style='color: #ff9fec'&gt;=&lt;/span&gt; &lt;span style='color: #dd0000'&gt;"00:1E:DC:1E:82:AA"&lt;/span&gt; &lt;span style='color: #808080'&gt;&lt;i&gt;# can be found with `hcitool scan`&lt;/i&gt;&lt;/span&gt;
&lt;span style='color: #bb1188'&gt;&lt;b&gt;CHDIR_TO_CAMERA_ALBUM&lt;/b&gt;&lt;/span&gt; &lt;span style='color: #ff9fec'&gt;=&lt;/span&gt; &lt;span style='color: #dd0000'&gt;"obexftp --bluetooth &lt;/span&gt;&lt;span style='color: #008000'&gt;#{&lt;/span&gt;&lt;span style='color: #bb1188'&gt;&lt;b&gt;PHONE_MAC&lt;/b&gt;&lt;/span&gt;&lt;span style='color: #008000'&gt;}&lt;/span&gt;&lt;span style='color: #dd0000'&gt; --chdir 'Phone memory' --chdir 'Camera album'"&lt;/span&gt;

output &lt;span style='color: #ff9fec'&gt;=&lt;/span&gt; &lt;span style='color: #aa3000'&gt;`&lt;/span&gt;&lt;span style='color: #008000'&gt;#{&lt;/span&gt;&lt;span style='color: #bb1188'&gt;&lt;b&gt;CHDIR_TO_CAMERA_ALBUM&lt;/b&gt;&lt;/span&gt;&lt;span style='color: #008000'&gt;}&lt;/span&gt;&lt;span style='color: #aa3000'&gt; --list`&lt;/span&gt;
photos_folder &lt;span style='color: #ff9fec'&gt;=&lt;/span&gt; output&lt;span style='color: #4000a7'&gt;.match&lt;/span&gt;(&lt;span style='color: #4a5704'&gt;/folder name="(.+?)"/&lt;/span&gt;)&lt;span style='color: #ff9fec'&gt;[&lt;/span&gt;&lt;span style='color: #0000ff'&gt;1&lt;/span&gt;&lt;span style='color: #ff9fec'&gt;]&lt;/span&gt;

output &lt;span style='color: #ff9fec'&gt;=&lt;/span&gt; &lt;span style='color: #aa3000'&gt;`&lt;/span&gt;&lt;span style='color: #008000'&gt;#{&lt;/span&gt;&lt;span style='color: #bb1188'&gt;&lt;b&gt;CHDIR_TO_CAMERA_ALBUM&lt;/b&gt;&lt;/span&gt;&lt;span style='color: #008000'&gt;}&lt;/span&gt;&lt;span style='color: #aa3000'&gt; --chdir '&lt;/span&gt;&lt;span style='color: #008000'&gt;#{&lt;/span&gt;photos_folder&lt;span style='color: #008000'&gt;}&lt;/span&gt;&lt;span style='color: #aa3000'&gt;' --list`&lt;/span&gt;
photos &lt;span style='color: #ff9fec'&gt;=&lt;/span&gt; output&lt;span style='color: #4000a7'&gt;.scan&lt;/span&gt;(&lt;span style='color: #4a5704'&gt;/file name="(.+?)"/&lt;/span&gt;)&lt;span style='color: #4000a7'&gt;.flatten&lt;/span&gt;

photos&lt;span style='color: #4000a7'&gt;.each&lt;/span&gt; &lt;b&gt;do&lt;/b&gt; &lt;span style='color: #ff9fec'&gt;|&lt;/span&gt;photo&lt;span style='color: #ff9fec'&gt;|&lt;/span&gt;
  &lt;span style='color: #aa3000'&gt;`&lt;/span&gt;&lt;span style='color: #008000'&gt;#{&lt;/span&gt;&lt;span style='color: #bb1188'&gt;&lt;b&gt;CHDIR_TO_CAMERA_ALBUM&lt;/b&gt;&lt;/span&gt;&lt;span style='color: #008000'&gt;}&lt;/span&gt;&lt;span style='color: #aa3000'&gt; --chdir '&lt;/span&gt;&lt;span style='color: #008000'&gt;#{&lt;/span&gt;photos_folder&lt;span style='color: #008000'&gt;}&lt;/span&gt;&lt;span style='color: #aa3000'&gt;' --get &lt;/span&gt;&lt;span style='color: #008000'&gt;#{&lt;/span&gt;photo&lt;span style='color: #008000'&gt;}&lt;/span&gt;&lt;span style='color: #aa3000'&gt; --delete &lt;/span&gt;&lt;span style='color: #008000'&gt;#{&lt;/span&gt;photo&lt;span style='color: #008000'&gt;}&lt;/span&gt;&lt;span style='color: #aa3000'&gt;`&lt;/span&gt;
&lt;b&gt;end&lt;/b&gt;
&lt;/pre&gt;&lt;p&gt;It was the best thing KDE 4 forced me to do so far. No more clicking around with mouse, console is your best friend :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-4328756818839831378?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=O5Lbm2HB"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=QjuynWnu"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=QjuynWnu" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=CipLEpiy"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=CipLEpiy" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=avtXsh9p"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=avtXsh9p" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=HBxgp5J5"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=129" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/ehe8XAqhD3U" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-08T05:44:40.383-08:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2008/11/bluetooth-in-kubuntu-810-by-hands.html</feedburner:origLink></item><item><title>Test::Unit design</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/q89OdDaCIX8/testunit-design.html</link><category>ruby</category><category>test::unit</category><category>design</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Mon, 03 Nov 2008 04:46:05 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-1118719677546603934</guid><description>&lt;p&gt;A while ago I &lt;a href='http://codingmatters.blogspot.com/2008/10/junit-design.html'&gt;posted&lt;/a&gt; a couple of diagrams which I used to make sense of JUnit design. Almost at the same of drawing those ones I took a look at implementation of Test::Unit and RSpec frameworks. As a consequence here is a simplified overview of Test::Unit design.&lt;/p&gt;&lt;h2 id='design_in_general'&gt;Design in general&lt;/h2&gt;&lt;p&gt;&lt;img src='http://lh3.ggpht.com/_VrU0ZHx_ziY/SQ7qjxm5nfI/AAAAAAAAAFc/SyNidq9ccMQ/testunit1.jpg' alt='testunit overview' /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Given a TestSuit, TestRunner creates TestRunnerMediator, registers itself as TestRunnerMediator listener and then asks TestRunnerMediator to execute tests.&lt;/li&gt;&lt;li&gt;TestRunnerMediator creates TestResult, registers itself as TestResult listener and then relays request to execute tests to TestSuite.&lt;/li&gt;&lt;li&gt;TestSuite contains TestCase instances for each test method and upon request runs each of them.&lt;/li&gt;&lt;li&gt;TestCases actually execute test code (including &lt;code&gt;setup&lt;/code&gt; and &lt;code&gt;teardown&lt;/code&gt; methods) and notify TestResult on assertions, errors and failures. These events are propagated to TestRunner which actually provides some feedback to user, for example, write results to console.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;All notifications are implemented using Observer module, so MediatorListener and TestResultListener interfaces in the diagram show roles played by classes in collaboration rather than some kind of interfaces in terms of the language.&lt;/p&gt;&lt;h2 id='how_it_actually_works'&gt;How it actually works&lt;/h2&gt;&lt;p&gt;&lt;img src='http://lh3.ggpht.com/_VrU0ZHx_ziY/SQ7qkJLQ14I/AAAAAAAAAFk/jE9rb65WUko/testunit2.jpg' alt='testunit autorunner' /&gt;&lt;/p&gt;&lt;p&gt;Since the above description is somewhat abstract here is how Test::Unit is actually used from scripts if you ran TestCase as a standalone script:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;When you require &lt;code&gt;test/unit&lt;/code&gt; module in a test script, Unit adds a block to be executed when script is about to exit through the &lt;code&gt;Kernel::at_exit&lt;/code&gt; method. This block asks the AutoRunner class to execute tests.&lt;/li&gt;&lt;li&gt;AutoRunner creates OptionsParser which reads parameters from command line and based on them creates TestRunner. Also AutoRunner chooses and creates Collector instance which finds tests and packs them into a TestSuite.&lt;/li&gt;&lt;li&gt;AutoRunner passes TestSuite to TestRunner and asks it to run tests.&lt;/li&gt;&lt;li&gt;Given a TestSuit, TestRunner creates TestRunnerMediator&amp;#8230; etc&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Should you want to see available TestRunners, Collectors or other options, the AutoRunner is probably the best place to get started. Another interesting place to go (it&amp;#8217;s obvious and can be easily found from Test::Unit documentation but anyway) is Test::Unit::Assertions module, which contains available assertions.&lt;/p&gt;&lt;p&gt;If you don&amp;#8217;t want to use AutoRunner, there is another way to execute tests which is to manually create TestRunner and pass to it a TestSuite (in this case Unit module won&amp;#8217;t register block to execute at exit and AutoRunner won&amp;#8217;t be used). It looks like this (code snippet is taken from Test::Unit rdoc):&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;require &amp;#8216;test/unit/ui/console/testrunner&amp;#8217;&lt;/p&gt;&lt;p&gt;Test::Unit::UI::Console::TestRunner.run(TCMyTest)&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;P.S. there is also a bit confusing (at least for me) RUnit package bundled with Ruby. I couldn&amp;#8217;t find any authoritative information about how it&amp;#8217;s related to Test::Unit. Judging from the code, it seems to be deprecated API left for backward compatibility which shouldn&amp;#8217;t be used in new code.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-1118719677546603934?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=FPfA1sMx"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=81W0cXvL"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=81W0cXvL" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=kZ3WEJg3"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=kZ3WEJg3" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=jK5SQppa"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=jK5SQppa" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=7YowAgaD"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=129" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/q89OdDaCIX8" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-03T04:46:05.453-08:00</app:edited><media:thumbnail url="http://lh3.ggpht.com/_VrU0ZHx_ziY/SQ7qjxm5nfI/AAAAAAAAAFc/SyNidq9ccMQ/s72-c/testunit1.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2008/11/testunit-design.html</feedburner:origLink></item><item><title>JUG with Joshua Bloch</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/mylcglBa5N4/jug-with-joshua-bloch.html</link><category>java</category><category>jug</category><category>josh bloch</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Mon, 20 Oct 2008 13:03:28 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-1815042456937431897</guid><description>&lt;p&gt;The weekend before the last one I was lucky enough to attend &lt;a href='http://www.jug.ru'&gt;JUG&lt;/a&gt; meeting with Josh Bloch invited as a speaker. The event took place in St. Petersburg. It was a bit far away to go for me, but even though I&amp;#8217;ve never been a huge fan of Josh Bloch (I read and enjoyed Effective Java :)) I had decided it was worth going and was right.&lt;/p&gt;&lt;p&gt;Josh gave two talks: &amp;#8220;More Effective Java&amp;#8221; which essentially highlighted some new parts of the &lt;a href='http://java.sun.com/docs/books/effective/'&gt;2nd edition of Effective Java&lt;/a&gt; and &amp;#8220;How to Design a Good API and Why it Matters&amp;#8221; talk which had also a lot in common with the Effective Java book. The bad thing for me was that I had read Josh&amp;#8217;s book before (including 2nd edition) and I have even watched him giving a talk about good API on the Internet, so I&amp;#8217;ve read or heard probably about 98% of content. I don&amp;#8217;t mean I &lt;em&gt;know&lt;/em&gt; all these things really well, but still it wasn&amp;#8217;t exciting. There was a chance to see java-puzzlers with generics but unfortunately everyone voted against it in favor of API speech. Josh Bloch is an excellent and quite articulate speaker so it still was a real pleasure to listen to him. The good side of it is should you be interested in Josh Bloch&amp;#8217;s views on how to develop software and pieces of advice, you can read his book (or may be also watch a video) to get the most of it&amp;#8230; 98% or so :)&lt;/p&gt;&lt;p&gt;The most surprising for me was how everything except the speech itself went. First off, it was Josh Bloch setting up his (well.. Google&amp;#8217;s) laptop and projector totally on his own sometimes crawling among the chairs. It&amp;#8217;s by no means a complaint about organization of the event, it&amp;#8217;s just was quite different from what I had expected or seen on MS events. Another thing was that there was almost no excitement about Josh Bloch, although, he was very friendly readily posing for photographs and singing books. After the speeches there were not more than 20 people out of more than 100 who decided to join the dinner and at most 7 of them who were talking or listening to Josh. For me it was the best part where everyone could ask any questions and as many of them as they would like. I admit I wasn&amp;#8217;t prepared and didn&amp;#8217;t have interesting technical questions :( Still it was a great experience to see in details what the man who influenced java-world a great deal thinks, what values has. It can be found &amp;#8220;offline&amp;#8221; but real-life experience is much better and it surely changed my understanding of Josh Bloch&amp;#8217;s writings and made me think how geeky I got over the last few years.&lt;/p&gt;&lt;p&gt;These are The Only Really Important Answers ;) I got (reproduced as I remembered them):&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Q: What IDE do you use?&lt;/p&gt;&lt;p&gt;A: In our team at Google we use IntelliJ, so it&amp;#8217;s IntelliJ. I haven&amp;#8217;t used other IDEs a lot.&lt;/p&gt;&lt;p&gt;Q: What OS do you use?&lt;/p&gt;&lt;p&gt;A: We use Ubuntu at Google. I have several XP boxes at home and I used to have Mac. I hate all OS equally :)&lt;/p&gt;&lt;/blockquote&gt;&lt;a href='http://2.bp.blogspot.com/_VrU0ZHx_ziY/SPzhZWuSXWI/AAAAAAAAAEs/0dEIiWQy9H4/s1600-h/DSC00278.JPG' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/SPzhZWuSXWI/AAAAAAAAAEs/0dEIiWQy9H4/s400/DSC00278.JPG' border='0' id='BLOGGER_PHOTO_ID_5259326290574597474' alt='' style='cursor:pointer; cursor:hand;' /&gt;&lt;/a&gt;&lt;a href='http://2.bp.blogspot.com/_VrU0ZHx_ziY/SPzhZ7WEiNI/AAAAAAAAAE0/GXtuEDcIc_o/s1600-h/DSC00282.JPG' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;&lt;img src='http://2.bp.blogspot.com/_VrU0ZHx_ziY/SPzhZ7WEiNI/AAAAAAAAAE0/GXtuEDcIc_o/s400/DSC00282.JPG' border='0' id='BLOGGER_PHOTO_ID_5259326300405139666' alt='' style='cursor:pointer; cursor:hand;' /&gt;&lt;/a&gt;&lt;a href='http://4.bp.blogspot.com/_VrU0ZHx_ziY/SPzhaK9tnII/AAAAAAAAAE8/axbugyv3j9I/s1600-h/DSC00293.JPG' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'&gt;&lt;img src='http://4.bp.blogspot.com/_VrU0ZHx_ziY/SPzhaK9tnII/AAAAAAAAAE8/axbugyv3j9I/s400/DSC00293.JPG' border='0' id='BLOGGER_PHOTO_ID_5259326304597941378' alt='' style='cursor:pointer; cursor:hand;' /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-1815042456937431897?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=nxx94feu"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=YvyTRlUr"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=YvyTRlUr" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=Jk89k6uQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=Jk89k6uQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=YHxdekKl"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=YHxdekKl" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=pK8dC95v"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=129" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/mylcglBa5N4" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-20T13:03:28.079-07:00</app:edited><media:thumbnail url="http://2.bp.blogspot.com/_VrU0ZHx_ziY/SPzhZWuSXWI/AAAAAAAAAEs/0dEIiWQy9H4/s72-c/DSC00278.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codingmatters.blogspot.com/2008/10/jug-with-joshua-bloch.html</feedburner:origLink></item><item><title>JUnit design</title><link>http://feedproxy.google.com/~r/blogspot/SvAh/~3/HEaw129KbrM/junit-design.html</link><category>java</category><category>tdd</category><category>design</category><author>noreply@blogger.com (Dmitry Kandalov)</author><pubDate>Tue, 21 Oct 2008 12:36:04 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-3821250806993950666.post-5286200913519750161</guid><description>&lt;h1 id='junit_design'&gt;JUnit design&lt;/h1&gt;&lt;p&gt;It started a while ago when I read &lt;a href='http://blog.jayfields.com/2008/08/be-your-start-up.html'&gt;Jay Fields&amp;#8217; inspiring post&lt;/a&gt; about being your own start-up where he mentioned two books one should read. One of the books was &lt;a href='http://junit.sourceforge.net/doc/cookstour/cookstour.htm'&gt;My Job Went to India&lt;/a&gt;. Despite its weird name, it is a great writing with honest pieces of advice how to be a better developer. After reading and truly enjoying it, I realized the worst thing can happen now is that I mark it as &amp;#8220;read&amp;#8221; on the list and move on. So I decided to follow some of the ideas from &amp;#8220;act on it&amp;#8221;-parts. One of them is to find new ideas and inspiration from projects that are generally considered good.&lt;/p&gt;&lt;p&gt;Here is just a high-level overview of how junit works in my over-simplified interpretation in case I loose a piece of paper I drew it on :) For more substantial overview of junit 3.8, take a look at &lt;a href='http://junit.sourceforge.net/doc/cookstour/cookstour.htm'&gt;cooks&amp;#8217; tour&lt;/a&gt; or &lt;a href='http://www.riehle.org/wp-content/uploads/2008/04/sen-2008-03-junit-doc.pdf'&gt;excellent paper by Dirk Riehle&lt;/a&gt;.&lt;/p&gt;&lt;h2 id='junit_38'&gt;JUnit 3.8&lt;/h2&gt;&lt;p&gt;&lt;img src='http://lh5.ggpht.com/dmitry.kandalov/SO0ckUT6kMI/AAAAAAAAADI/zgDVhFKBvIE/junit3.8.jpg' alt='junit 3.8 overview' /&gt;&lt;/p&gt;&lt;p&gt;Given a class TestRunner tries to use it as a TestSuite. If it&amp;#8217;s not a TestSuite, TestRunner creates TestSuite with TestCases for each test method in this class. TestRunner creates TestResult object which collects results of running tests and passes them to TestListeners. Tests notify TestResult which passes events to TestListeners. TestRunners bundled with junit are also TestListeners since they subclass BaseTestRunner.&lt;/p&gt;&lt;h2 id='junit_4x'&gt;JUnit 4.x&lt;/h2&gt;&lt;p&gt;&lt;img src='http://lh3.ggpht.com/dmitry.kandalov/SO0ckXyocCI/AAAAAAAAADQ/XoDzkZWIzEI/junit4.5.jpg' alt='junit 4.x overview' /&gt;&lt;/p&gt;&lt;p&gt;Given a class JUnitCore creates a Request. Request decides which Runner to use for executing tests (this is where @RunWith annotation is used; see &lt;a href='http://feeds.feedburner.com/~r/PlanetTw/~3/406379119/write-your-own-junit-runner.html'&gt;Mark Burnett&amp;#8217;s post&lt;/a&gt; for example of how to create custom Runner). Runner finds test methods and executes them. For each test Runner creates Description which is sent to RunNotifier and then passed to RunListener. After tests are executed JUnitCore sends Result to RunNotifier and RunListener.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3821250806993950666-5286200913519750161?l=codingmatters.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=VLnabMIx"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=YbVnOHzi"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=YbVnOHzi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=L3vSXsnl"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=L3vSXsnl" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=fFFiXhP0"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?i=fFFiXhP0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/blogspot/SvAh?a=3mMcXBBV"&gt;&lt;img src="http://feeds.feedburner.com/~f/blogspot/SvAh?d=129" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/SvAh/~4/HEaw129KbrM" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-21T12:36:04.513-07:00</app:edited><media:thumbnail url="http://lh5.ggpht.com/dmitry.kandalov/SO0ckUT6kMI/AAAAAAAAADI/zgDVhFKBvIE/s72-c/junit3.8.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><enclosure url="http://www.riehle.org/wp-content/uploads/2008/04/sen-2008-03-junit-doc.pdf" length="600213" type="application/pdf" /><media:content url="http://www.riehle.org/wp-content/uploads/2008/04/sen-2008-03-junit-doc.pdf" fileSize="600213" type="application/pdf" /><feedburner:origLink>http://codingmatters.blogspot.com/2008/10/junit-design.html</feedburner:origLink></item><media:credit role="author">Dmitry Kandalov</media:credit><media:rating>nonadult</media:rating></channel></rss>

