<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-12467669</atom:id><lastBuildDate>Sat, 21 Nov 2009 21:33:16 +0000</lastBuildDate><title>Jay Fields' Thoughts</title><description>experiences in software development</description><link>http://blog.jayfields.com/</link><managingEditor>blogger@jayfields.com (Jay Fields)</managingEditor><generator>Blogger</generator><openSearch:totalResults>437</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>5</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/jayfields/mjKQ" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-12467669.post-8223643882769735783</guid><pubDate>Tue, 03 Nov 2009 15:06:00 +0000</pubDate><atom:updated>2009-11-03T10:06:00.400-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">languages</category><title>Polyglot World</title><description>At QCon 2008 &lt;a href="http://steve.vinoski.net/blog/"&gt;Steve Vinoski&lt;/a&gt; told me he uses at least 4 languages pretty much every day. At the time I thought 4 seemed like a lot of languages to use. Are we ready for a world where programmers need to know so many languages?&lt;br /&gt;&lt;br /&gt;If you think about building a web application, you probably need to know a server-side language, HTML, Javascript, CSS, SQL, etc. Of course, there's no easy way to draw a line and say that those are, or are not all languages. I'm not sure the distinction matters, what does matter is having effective tools to get your job done. Maybe 4 languages isn't surprising.&lt;br /&gt;&lt;br /&gt;I've worked on projects where C# and SQL were all we used; however, I think those days are coming to an end.&lt;br /&gt;&lt;br /&gt;As an example, let's start with books. I'm currently reviewing Martin Fowler's upcoming DSL book. For his examples, Martin chose Java and C# where possible, and &lt;a href="http://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt; where a dynamic language was necessary. I think his language choices are pragmatic and wise. It's easy to agree and not give the idea another thought. However, his choice is a departure from his traditional usage of Java and C# exclusively.&lt;br /&gt;&lt;br /&gt;Martin didn't add a new language because he changed his mind about dynamic languages, he added a new language because our industry changed it's mind about dynamic languages. Dynamic languages are now an acceptable choice for many projects, and an appropriate language addition for authors looking to appeal to the widest audience.&lt;br /&gt;&lt;br /&gt;If Martin ever publishes another version of &lt;a href="http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672"&gt;Refactoring&lt;/a&gt;, I expect it will have examples in several different languages. &lt;a href="http://amzn.com/0321603508"&gt;Refactoring: Ruby Edition&lt;/a&gt; contains several refactorings that are impossible to do in Java and C#. I have no idea what languages will be popular at the time of another Refactoring release; however, I think we will see a diverse set of languages and refactorings that target specific languages.&lt;br /&gt;&lt;br /&gt;However, the polyglot movement can be found in the industry even more so than in books. &lt;a href="http://twitter.com"&gt;Twitter&lt;/a&gt; is known to use both Ruby and Scala. &lt;a href="http://google.com"&gt;Google&lt;/a&gt; uses C++, Java, Python, and Javascript. At &lt;a href="http://drw.com"&gt;DRW&lt;/a&gt; Trading we use any language that will help us get to market faster. Any given day, working solely on my project, I could be working with Java, C#, &lt;a href="http://clojure.org"&gt;Clojure&lt;/a&gt;, Ruby or other even more interesting options. Steve's "4 language" statement doesn't surprise me at all these days.&lt;br /&gt;&lt;br /&gt;You can also look at the multiple languages on the CLR and the JVM as further proof that as an industry we are willing to look to multiple languages to solve individual problems. The interoperability allows us to use the languages and paradigms we prefer for specific tasks, while working toward a greater solution. From personal experience, using Java and Clojure together has been a big productivity boost on several occasions.&lt;br /&gt;&lt;br /&gt;As I already mentioned, in the web world you often need to master several languages to be effective. As a young developer, learning each language is probably a daunting task. However, I think having several targeted languages is part of the reason that web application development has been so successful. Targeted languages often give you the power and simplicity that allow you to get your job done without thinking about overly complex abstractions. &lt;br /&gt;&lt;br /&gt;People often forget that "one language to rule them all" also implies that the language will attempt normalize everything. However, there are obviously efficiency gains to be had if you choose languages that play to the strengths of a paradigm or platform. The web proves this by having languages that target and solve specific problems. I wouldn't want to write CSS or Javascript in another language, even if it allowed me to solve all my problems with only 1 language. I prefer languages that increase my effectiveness to languages that reduce my learning requirements.&lt;br /&gt;&lt;br /&gt;Ruby took a bold and productive step by introducing features that worked exclusively on Linux. As a result, several tasks are very simple to do on Linux and impossible on Windows.I applaud the choice. It makes my life easier when I'm on Linux, and I know I have to find another solution when I'm working on Windows. I'll take those options over some poor abstraction that feels painful on both platforms.&lt;br /&gt;&lt;br /&gt;And, that's where I see our industry moving. Languages targeted at specific problems and run on specific platforms. The languages will be easier to create and use. There's been a movement in our industry towards simplicity for some time. This is just another logical step in that direction.&lt;br /&gt;&lt;br /&gt;The days of one language for all problems and platforms are dwindling, which is nice. I prefer the polygot world.&lt;div class="blogger-post-footer"&gt;&lt;br/&gt;&lt;a href="http://www.jayfields.com"&gt;&amp;copy; Jay Fields - www.jayfields.com&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12467669-8223643882769735783?l=blog.jayfields.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=9rz8HXgrpzc:qLBoimXiGss:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=9rz8HXgrpzc:qLBoimXiGss:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=9rz8HXgrpzc:qLBoimXiGss:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=9rz8HXgrpzc:qLBoimXiGss:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=9rz8HXgrpzc:qLBoimXiGss:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=9rz8HXgrpzc:qLBoimXiGss:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=9rz8HXgrpzc:qLBoimXiGss:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=9rz8HXgrpzc:qLBoimXiGss:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jayfields/mjKQ/~4/9rz8HXgrpzc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jayfields/mjKQ/~3/9rz8HXgrpzc/polyglot-world.html</link><author>blogger@jayfields.com (Jay Fields)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.jayfields.com/2009/11/polyglot-world.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-12467669.post-2992793256023645318</guid><pubDate>Thu, 22 Oct 2009 01:08:00 +0000</pubDate><atom:updated>2009-10-21T21:13:08.712-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ruby</category><category domain="http://www.blogger.com/atom/ns#">refactoring</category><title>Refactoring: Ruby Edition available.</title><description>Refactoring: Ruby Edition is available (and In Stock) on &lt;a href="http://amzn.com/0321603508"&gt;amazon.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://amzn.com/0321603508"&gt;&lt;img src="http://www.jayfields.com/refactoring.jpg"/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Sorry it took so long, I hope it is worth the wait.&lt;div class="blogger-post-footer"&gt;&lt;br/&gt;&lt;a href="http://www.jayfields.com"&gt;&amp;copy; Jay Fields - www.jayfields.com&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12467669-2992793256023645318?l=blog.jayfields.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=hovygaOmzAw:Tt58T8tYdGE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=hovygaOmzAw:Tt58T8tYdGE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=hovygaOmzAw:Tt58T8tYdGE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=hovygaOmzAw:Tt58T8tYdGE:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=hovygaOmzAw:Tt58T8tYdGE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=hovygaOmzAw:Tt58T8tYdGE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=hovygaOmzAw:Tt58T8tYdGE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=hovygaOmzAw:Tt58T8tYdGE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jayfields/mjKQ/~4/hovygaOmzAw" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jayfields/mjKQ/~3/hovygaOmzAw/refactoring-ruby-edition-available.html</link><author>blogger@jayfields.com (Jay Fields)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://blog.jayfields.com/2009/10/refactoring-ruby-edition-available.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-12467669.post-3225755954994781096</guid><pubDate>Thu, 10 Sep 2009 13:18:00 +0000</pubDate><atom:updated>2009-09-10T13:09:04.323-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">initial development time</category><category domain="http://www.blogger.com/atom/ns#">developers</category><category domain="http://www.blogger.com/atom/ns#">pressure</category><title>Pressure, Expressed in Initial Development Time</title><description>&lt;blockquote&gt;def &lt;span style="font-weight:bold;"&gt;Initial Development Time&lt;/span&gt;: In software development projects, initial development time (IDT) is the length of time it takes from the project's first line of code until the business derives notable value from it.&lt;/blockquote&gt;I've done plenty of projects in my career, some with an IDT of a few months and some with an IDT of a year or more. Based on those projects I've decided that I like the following equation to express the pressure felt by a team at any given moment during the IDT.&lt;blockquote&gt;pressure = &lt;a href="http://en.wikipedia.org/wiki/Fibonacci_number"&gt;Fibonacci&lt;/a&gt;(current month of IDT)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;note:&lt;/span&gt;This equation assumes all other variables are normal. Obviously a team that must finish a project in a month or suffer dire consequences will feel a much different amount of pressure.&lt;/blockquote&gt;During the first month, the team feels 0 (which represents almost no) pressure. There's no legacy code, few broken builds, no requirements issues. During the second and the third month, the team feels 1 (which represents more, but still very little) pressure. The first mistakes and hurdles have been found. The architecture is being pushed. &lt;br /&gt;&lt;br /&gt;The following months follow the fibonacci sequence. At month four, the team feels a pressure of 2. At month five, the team feels a pressure of 3. And, so on.&lt;br /&gt;&lt;br /&gt;The sequence isn't meant to be out of 100, 1000, or any other number. It's purpose is to show the progression of pressure as the as months of IDT pass. In an ideal world, a manager would understand that a team under extreme pressure will underperform, and the manager would do everything in his or her power to reduce the IDT.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Consequences&lt;/span&gt;&lt;br /&gt;Pressure can be good in moderation. Many Agile teams have iteration point goals which pressure the team to get a reasonable amount of work done per iteration. Unfortunately, pressure also tends to have the &lt;a href="http://en.wikipedia.org/wiki/Boiling_frog"&gt;boiling frog&lt;/a&gt; effect.&lt;br /&gt;&lt;br /&gt;Pressure often leads to compromises on quality. Far too often I've heard "let's just get this done, and then we'll clean it up." This is a good strategy if you are planning on cleaning immediately after completion (&lt;a href="http://en.wikipedia.org/wiki/Test-driven_development#Development_style"&gt;red/green/refactor&lt;/a&gt;). However, if you plan on cleaning it up "in the future", that step (the majority of the time) is forgotten. &lt;br /&gt;&lt;br /&gt;Fibonacci works well for this (quality related) equation also.&lt;blockquote&gt;% of code that "sucks" = min(80, Fibonacci(current month of IDT))&lt;/blockquote&gt;Most people wont admit that the code they are currently writing is poor, which helps explain why the percentage rarely reaches over 80%. Also, there's often some code that was written early, and never needed to be modified. Late in a project, looking at that code may be the only thing that keeps you sane.&lt;blockquote&gt;sidenote: 50% of the time "this code sucks" can be directly translated to "I didn't write this code". On a project with many months of IDT you are bound to experience some turn-over, thus the amount of code that "sucks" is destined to go up. And, even if the original code didn't suck, the modifications done by the person who only half-understands the code probably do suck.&lt;/blockquote&gt;Innovation also seems to suffer on projects with many months of IDT. A typical (well functioning) project team tends to spend 20-30% of their time experimenting with new ideas that will make them more productive in the future. When innovations are found the dividends often greatly exceed the original time investment. Even when no innovations are found, the team often benefits from the experience gained. &lt;br /&gt;&lt;br /&gt;Unfortunately, during IDT people begin to forget the value in innovation. They seem to visualize a path to the finish and charge down that path full speed with no regard for hurdles or environment changes. They are often unable to see the value in any time spent that doesn't already have "proven" value. Very soon, you begin to hear: "let's just get this done, and then we'll look at better solutions."&lt;br /&gt;&lt;br /&gt;Between (unclean? dirty?) poorly written code and lack of innovation, the chances of dragging a code base out of darkness dwindle quickly as the IDT months drag on.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Lies&lt;/span&gt;&lt;br /&gt;Many Agile believers will tell you that the problems with pressure can be alleviated with Milestones. This is patently false. A solution isn't valuable to a business until it provides notable business value. You may be 13 iterations into the project with 2 milestones behind you, but if the business isn't deriving value, you haven't done anything more than show them partially working software. Partially working software is great for building trust, but it alleviates zero pressure with respect to IDT.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Options&lt;/span&gt;&lt;br /&gt;The only real remedy to the negative consequences of a long IDT is to create a shorter IDT. There truly is no alternative.&lt;br /&gt;&lt;br /&gt;Unfortunately, some projects truly do take many months to deliver business value. I've found that some pressure can be alleviated if the team recognizes and adjusts to the pressure. &lt;br /&gt;&lt;br /&gt;The 3 most helpful things I've found are:&lt;ul&gt;&lt;li&gt;Weekly (scheduled) 1 on 1 discussions between the team lead and each member of the team.&lt;li&gt;Take vacation. One person out for a week isn't nearly as catastrophic as a team full of burnt out people.&lt;li&gt;Set aside, and always use, experimentation time. Innovations can give you a big boost that the project will definitely need in the long run.&lt;/ul&gt;Thanks to Lance Walton for feedback, and the phrase "Initial Development Time"&lt;div class="blogger-post-footer"&gt;&lt;br/&gt;&lt;a href="http://www.jayfields.com"&gt;&amp;copy; Jay Fields - www.jayfields.com&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12467669-3225755954994781096?l=blog.jayfields.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=RrjH8CopUFQ:cxmaABLnunY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=RrjH8CopUFQ:cxmaABLnunY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=RrjH8CopUFQ:cxmaABLnunY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=RrjH8CopUFQ:cxmaABLnunY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=RrjH8CopUFQ:cxmaABLnunY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=RrjH8CopUFQ:cxmaABLnunY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=RrjH8CopUFQ:cxmaABLnunY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=RrjH8CopUFQ:cxmaABLnunY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jayfields/mjKQ/~4/RrjH8CopUFQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jayfields/mjKQ/~3/RrjH8CopUFQ/pressure-expressed-in-initial.html</link><author>blogger@jayfields.com (Jay Fields)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://blog.jayfields.com/2009/09/pressure-expressed-in-initial.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-12467669.post-1753214295044398366</guid><pubDate>Thu, 20 Aug 2009 13:44:00 +0000</pubDate><atom:updated>2009-08-20T12:12:26.547-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">conference</category><category domain="http://www.blogger.com/atom/ns#">developers</category><category domain="http://www.blogger.com/atom/ns#">staying current</category><title>Staying Current: A Software Developer's Responsibility</title><description>I have a personal hatred for weekend conferences*. To me, a weekend conference ensures that I'll be "working" for 12 straight days.&lt;br /&gt;&lt;br /&gt;I understand that opinion isn't universal. &lt;br /&gt;&lt;br /&gt;Some people have problems getting time "off" to attend conferences. These situations feel like a fundamental misunderstanding of a software developer's responsibilities. Part of your (software developing) job is staying up on current technologies. That means doing some research during your day.&lt;br /&gt;&lt;br /&gt;(almost directly stolen from Ward on &lt;a href="http://c2.com/cgi/wiki?WardExplainsDebtMetaphor"&gt;technical debt&lt;/a&gt;)&lt;br /&gt;If you spend your entire day coding and never looking at new things, you accrue productivity debt. In the short term (say the last week of a release), it makes sense to take on a little debt. However, in the long term, assuming little or no payment, the interest (where interest equals the gap between your skills and the current solutions) will render you a NZPP (Net-Zero Producing Programmer). In a typical organization you can coast as a NZPP for around 6 months and slowly transition to a &lt;a href="http://blog.jayfields.com/2009/01/cost-of-net-negative-producing.html"&gt;NNPP&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It is your responsibility not to become a NZPP (or NNPP). Most talented software developers refuse to work with NZPPs. At the point that you become NZPP, you usually have to declare bankruptcy (with regard to software development). You generally have two choices: take a much lower paying job where you can learn new things or move into another role. If you want to be a software developer, neither of these outcomes is desirable.&lt;br /&gt;&lt;br /&gt;Luckily, you have the power to avoid becoming a NZPP. Most employers will happily buy you technical books and send you to technical conferences. In my opinion, whether or not you took advantage of these benefits should be noted on your performance review. Not staying current as a software developer, especially when the opportunity is offered to you, is software malpractice.&lt;br /&gt;&lt;br /&gt;I once created a list of things I look for in potential team-mates.&lt;ul&gt;&lt;li&gt;Have you tried Test Driven Development? Can you name something you liked and something you disliked?&lt;li&gt;What language(s) that are gaining popularity, but not yet mainstream, have you written Hello World in?&lt;li&gt;Do you read books or blogs looking for new ideas at least (on average) once every two weeks?&lt;li&gt;Do you at least attempt to learn a new language every year?&lt;li&gt;Have you ever run a code coverage or cyclomatic complexity tool against your codebase?&lt;/ul&gt;A commenter said something along the lines of&lt;blockquote&gt;Not everyone has the personal free time to dedicate to doing all of these things&lt;/blockquote&gt;And, that is the fundamental flaw. Employees (and even some employers) seem to think that these are activities that should be done in your off time. I can't disagree more. These are things that a responsible developer needs to do as part of their job, thus it can be done during work hours.&lt;br /&gt;&lt;br /&gt;20% time isn't something Google invented, it's just something they named, formalized and made popular. The activity itself is something good software developers have been doing for years. I applaud Google for making it a standard, thus ensuring that it's employees always have the opportunity to stay current. However, your company doesn't need to standardize on 20% time for you to stay current. &lt;br /&gt;&lt;br /&gt;It's your responsibility to make time in your day to read a book or a blog. &lt;br /&gt;&lt;br /&gt;You should also take advantage of a company sponsored trip to a conference. If you've attended conferences before and derived little value, I highly suggest the &lt;a href="http://qcon.infoq.com/"&gt;QCon&lt;/a&gt; conferences and &lt;a href="http://jaoo.dk/"&gt;JAOO&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Once you start doing research as part of your job you'll find that conferences are just like work, except the focus is 100% on research. And, it's not something you want (or should have to) spend your personal time on, it's just another productive day of doing what you have a responsibility to do.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;* Which is why Josh and I run &lt;a href="http://speakerconf.com/"&gt;SpeakerConf&lt;/a&gt; Tuesday-Thursday. You can travel to, attend and travel home without missing a weekend day.&lt;div class="blogger-post-footer"&gt;&lt;br/&gt;&lt;a href="http://www.jayfields.com"&gt;&amp;copy; Jay Fields - www.jayfields.com&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12467669-1753214295044398366?l=blog.jayfields.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=nrIGQqQQLN8:XUGioouje84:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=nrIGQqQQLN8:XUGioouje84:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=nrIGQqQQLN8:XUGioouje84:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=nrIGQqQQLN8:XUGioouje84:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=nrIGQqQQLN8:XUGioouje84:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=nrIGQqQQLN8:XUGioouje84:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=nrIGQqQQLN8:XUGioouje84:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=nrIGQqQQLN8:XUGioouje84:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jayfields/mjKQ/~4/nrIGQqQQLN8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jayfields/mjKQ/~3/nrIGQqQQLN8/staying-current-software-developers.html</link><author>blogger@jayfields.com (Jay Fields)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">14</thr:total><feedburner:origLink>http://blog.jayfields.com/2009/08/staying-current-software-developers.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-12467669.post-4451093292858873289</guid><pubDate>Tue, 18 Aug 2009 03:38:00 +0000</pubDate><atom:updated>2009-08-18T07:47:43.970-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">clojure</category><category domain="http://www.blogger.com/atom/ns#">macro</category><title>Macros Facilitate Expressive Code</title><description>Someone once asked me if I thought Clojure was more expressive than even Ruby. I didn't have enough information to form an opinion then, and I still don't now. However, I recently noticed something that led me to believe the answer could actually be yes.&lt;br /&gt;&lt;br /&gt;I was looking through the code of &lt;a href="http://github.com/richhickey/clojure/blob/2098f5d57ecf3affb09a4cdaf2e01ad4de861eef/src/clj/clojure/test.clj"&gt;clojure.test&lt;/a&gt; on Friday and I noticed something interesting. In clojure.test, the form(s) passed to the "is" macro are wrapped by a try/catch.  It caught my eye because I often want to do the same thing in other languages, and usually I have to settle for much less elegant solutions.&lt;br /&gt;&lt;br /&gt;Here's a bit of example code to help create some context&lt;pre&gt;(deftest a-test&lt;br /&gt;  (is (= 1 (some-function-that-throws-an-exception)))&lt;br /&gt;  (println "this code still executes"))&lt;/pre&gt;For this example to work you'll have to ignore the fact that you probably don't want this behavior. In practice I prefer my tests to abort on the first failing assertion; however, in this blog entry I'm focusing on what's happening, not what I theoretically prefer.&lt;br /&gt;&lt;br /&gt;In the example I call a function the same way I would anywhere else, and the framework has full control over what happens if my function throws an exception. This is accomplished when the "is" macro takes the forms and manipulates them into something similar to the original code, but with additional capabilities.&lt;br /&gt;&lt;br /&gt;This particular example struck me as one where macros allow you to write only what you want, and the macro adds the additional behavior that you desire. However, the key is, you don't have to do anything special to get this additional behavior.&lt;br /&gt;&lt;br /&gt;Consider trying to do the same thing in Ruby. In Test::Unit you would need an assert method that took a block.&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="source source_ruby"&gt;&lt;span class="meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby"&gt;&lt;span class="keyword keyword_control keyword_control_def keyword_control_def_ruby"&gt;def&lt;/span&gt; &lt;span class="entity entity_name entity_name_function entity_name_function_ruby"&gt;safe_assert_equal&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  result &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby"&gt;yield&lt;/span&gt;&lt;br /&gt;  assert_equal result&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;first&lt;span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/span&gt; result&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;last&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;rescue&lt;/span&gt; &lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;Exception&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_key-value"&gt;=&amp;gt;&lt;/span&gt;e&lt;br /&gt;  puts e&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="meta meta_class meta_class_ruby"&gt;&lt;span class="keyword keyword_control keyword_control_class keyword_control_class_ruby"&gt;class&lt;/span&gt; &lt;span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby"&gt;Testable&lt;span class="entity entity_other entity_other_inherited-class entity_other_inherited-class_ruby"&gt; &lt;span class="punctuation punctuation_separator punctuation_separator_inheritance punctuation_separator_inheritance_ruby"&gt;&amp;lt;&lt;/span&gt; Test::Unit::TestCase&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby"&gt;&lt;span class="keyword keyword_control keyword_control_def keyword_control_def_ruby"&gt;def&lt;/span&gt; &lt;span class="entity entity_name entity_name_function entity_name_function_ruby"&gt;test_something&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    safe_assert_equal &lt;span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby"&gt;{&lt;/span&gt;&lt;span class="meta meta_syntax meta_syntax_ruby meta_syntax_ruby_start-block"&gt; &lt;/span&gt;&lt;span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;[&lt;/span&gt;&lt;span class="constant constant_numeric constant_numeric_ruby"&gt;1&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/span&gt; &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;2&lt;/span&gt;&lt;span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;]&lt;/span&gt; &lt;span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby"&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The additional syntax isn't drastically invasive; however, you are forcing additional syntax and requiring the understanding of why it's necessary.&lt;br /&gt;&lt;br /&gt;Of course, in Java things would be even less expressive. The most likely solution would be to put the assertEquals in a Runnable, but I'd be interested in hearing other ideas. Regardless of the solution, it would obviously be invasive and take away from the readability of the test.&lt;br /&gt;&lt;br /&gt;Being able to only say what is necessary is powerful. Stuart Halloway likes to talk about Essence and Ceremony, where Essence is the ability to say only what you want, and Ceremony is all the additional things you are required to say.&lt;br /&gt;&lt;br /&gt;Macros seem to be a powerful tool for those looking to write Ceremony-free code.&lt;div class="blogger-post-footer"&gt;&lt;br/&gt;&lt;a href="http://www.jayfields.com"&gt;&amp;copy; Jay Fields - www.jayfields.com&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12467669-4451093292858873289?l=blog.jayfields.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=3xpyCuixP4M:ltNWuYsNo-o:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=3xpyCuixP4M:ltNWuYsNo-o:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=3xpyCuixP4M:ltNWuYsNo-o:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=3xpyCuixP4M:ltNWuYsNo-o:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=3xpyCuixP4M:ltNWuYsNo-o:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=3xpyCuixP4M:ltNWuYsNo-o:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/jayfields/mjKQ?a=3xpyCuixP4M:ltNWuYsNo-o:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/jayfields/mjKQ?i=3xpyCuixP4M:ltNWuYsNo-o:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jayfields/mjKQ/~4/3xpyCuixP4M" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jayfields/mjKQ/~3/3xpyCuixP4M/macros-facilitate-expressive-code.html</link><author>blogger@jayfields.com (Jay Fields)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://blog.jayfields.com/2009/08/macros-facilitate-expressive-code.html</feedburner:origLink></item></channel></rss>
